OpenClonk
C4Menu.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 
18 /* In-game menu as used by objects, players, and fullscreen options */
19 
20 #include "C4Include.h"
21 #include "gui/C4Menu.h"
22 
23 #include "control/C4GameControl.h"
24 #include "game/C4Viewport.h"
25 #include "graphics/C4Draw.h"
27 #include "gui/C4MouseControl.h"
28 #include "lib/StdColors.h"
29 #include "object/C4Def.h"
30 #include "object/C4DefList.h"
31 #include "object/C4Object.h"
32 #include "player/C4Player.h"
33 #include "player/C4PlayerList.h"
34 
35 const int32_t C4MN_DefInfoWdt = 270, // default width of info windows
36  C4MN_DlgWdt = 270, // default width of dialog windows
37  C4MN_DlgLines = 5, // default number of text lines visible in a dialog window
38  C4MN_DlgLineMargin = 5, // px distance between text items
39  C4MN_DlgOptionLineMargin = 3, // px distance between dialog option items
40  C4MN_DlgPortraitWdt = 64, // size of portrait
41  C4MN_DlgPortraitIndent = 5; // space between portrait and text
42 
43 const int32_t C4MN_InfoCaption_Delay = 90;
44 
45 // -----------------------------------------------------------
46 // C4MenuItem
47 
48 C4MenuItem::C4MenuItem(C4Menu *pMenu, int32_t iIndex, const char *szCaption,
49  const char *szCommand, int32_t iCount, C4Object *pObject, const char *szInfoCaption,
50  C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, int32_t iStyle, bool fIsSelectable)
51  : C4GUI::Element(), Count(iCount), id(idID), Object(pObject), pSymbolObj(nullptr), pSymbolGraphics(nullptr), dwSymbolClr(0u),
52  fOwnValue(fOwnValue), iValue(iValue), fSelected(false), iStyle(iStyle), pMenu(pMenu),
53  iIndex(iIndex), IsSelectable(fIsSelectable), TextDisplayProgress(-1)
54 {
56  Symbol.Default();
57  SCopy(szCaption,Caption,C4MaxTitle);
58  SCopy(szCommand,Command,_MAX_FNAME+30);
59  SCopy(szCommand2,Command2,_MAX_FNAME+30);
60  SCopy(szInfoCaption,InfoCaption,C4MaxTitle);
61  // some info caption corrections
62  SReplaceChar(InfoCaption, 10, ' '); SReplaceChar(InfoCaption, 13, '|');
64 }
65 
67 {
68  Symbol.Clear();
69 }
70 
71 void C4MenuItem::DoTextProgress(int32_t &riByVal)
72 {
73  // any progress to be done?
74  if (TextDisplayProgress<0) return;
75  // if this is an option or empty text, show it immediately
76  if (IsSelectable || !*Caption) { TextDisplayProgress=-1; return; }
77  // normal text: move forward in unbroken message, ignoring markup
78  StdStrBuf sText(Caption);
79  C4Markup MarkupChecker(false);
80  const char *szPos = sText.getPtr(std::min<int>(TextDisplayProgress, sText.getLength()));
81  while (riByVal && *szPos)
82  {
83  MarkupChecker.SkipTags(&szPos);
84  if (!*szPos) break;
85  --riByVal;
86 
87  // Advance one UTF-8 character
88  uint32_t c = GetNextCharacter(&szPos);
89  // Treat embedded images {{XXX}} as one entity
90  if(c == '{' && *szPos == '{')
91  {
92  int32_t end = SCharPos('}', szPos);
93  if(end > 0 && szPos[end+1] == '}')
94  szPos += end + 2;
95  }
96  }
97  if (!*szPos)
99  else
100  TextDisplayProgress = szPos - Caption;
101 }
102 
103 bool C4MenuItem::IsDragElement()
104 {
105  // any constructibles can be dragged
106  C4Def *pDef = C4Id2Def(id);
107  return pDef && pDef->Constructable;
108 }
109 
110 int32_t C4MenuItem::GetSymbolWidth(int32_t iForHeight)
111 {
112  // Context or dialog menus
114  return std::max(Symbol.Wdt * iForHeight / std::max(Symbol.Hgt, 1.0f), static_cast<float>(iForHeight));
115  // Info menus
117  return Symbol.Wdt;
118  // no symbol
119  return 0;
120 }
121 
123 {
124  // get target pos
125  C4Facet cgoOut(cgo.Surface, cgo.TargetX + rcBounds.x, cgo.TargetY + rcBounds.y, rcBounds.Wdt, rcBounds.Hgt);
126  // Select mark
127  if (iStyle!=C4MN_Style_Info)
129  pDraw->DrawBoxDw(cgo.Surface, cgoOut.X, cgoOut.Y, cgoOut.X + cgoOut.Wdt - 1, cgoOut.Y + cgoOut.Hgt - 1, C4RGB(0xca, 0, 0));
130  // Symbol/text areas
131  C4Facet cgoItemSymbol,cgoItemText;
132  cgoItemSymbol=cgoItemText=cgoOut;
133  int32_t iSymWidth;
134  if ((iSymWidth = GetSymbolWidth(cgoItemText.Hgt)))
135  {
136  // get symbol area
137  cgoItemSymbol=cgoItemText.Truncate(C4FCT_Left, iSymWidth);
138  }
139  // cgoItemSymbol.Hgt is 0. This means rcBounds.Hgt is 0. That
140  // makes no sense at this point, so let's just draw in a
141  // square area at item y.
142  C4Facet cgoSymbolOut(cgoItemSymbol.Surface, cgoItemSymbol.X, cgoItemSymbol.Y, cgoItemSymbol.Wdt, cgoItemSymbol.Wdt);
143 
144  // Draw item symbol:
145  // Draw if there is no text progression at all (TextDisplayProgress==-1, or if it's progressed far enough already (TextDisplayProgress>0)
147  {
148  pSymbolObj->DrawPicture(cgoSymbolOut, false, nullptr);
149  }
151  {
152  pSymbolGraphics->Draw(cgoSymbolOut, dwSymbolClr ? dwSymbolClr : 0xffffffff, nullptr, 0, 0, nullptr);
153  }
154  else if (Symbol.Surface && TextDisplayProgress)
155  Symbol.DrawClr(cgoItemSymbol, true, dwSymbolClr);
156 
157  // Draw item text
158  pDraw->StorePrimaryClipper(); pDraw->SubPrimaryClipper(cgoItemText.X, cgoItemText.Y, cgoItemText.X+cgoItemText.Wdt-1, cgoItemText.Y+cgoItemText.Hgt-1);
159  switch (iStyle)
160  {
161  case C4MN_Style_Context:
162  pDraw->TextOut(Caption,::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y,C4Draw::DEFAULT_MESSAGE_COLOR,ALeft);
163  break;
164  case C4MN_Style_Info:
165  {
166  StdStrBuf sText;
167  ::GraphicsResource.FontRegular.BreakMessage(InfoCaption, cgoItemText.Wdt, &sText, true);
168  pDraw->TextOut(sText.getData(), ::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y);
169  break;
170  }
171  case C4MN_Style_Dialog:
172  {
173  // cut buffer at text display pos
174  char cXChg='\0'; int iStopPos = 0;
175  if (TextDisplayProgress>-1)
176  {
177  iStopPos = std::min<int>(TextDisplayProgress, strlen(Caption));
178  cXChg = Caption[iStopPos];
179  Caption[iStopPos] = '\0';
180  }
181  // display broken text
182  StdStrBuf sText;
183  ::GraphicsResource.FontRegular.BreakMessage(Caption, cgoItemText.Wdt, &sText, true);
184  pDraw->TextOut(sText.getData(),::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y);
185  // restore complete text
186  if (cXChg) Caption[iStopPos] = cXChg;
187  break;
188  }
189  }
191  // Draw count
193  {
194  char szCount[10+1];
195  sprintf(szCount,"%ix",Count);
196  pDraw->TextOut(szCount, ::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface, cgoItemText.X+cgoItemText.Wdt-1, cgoItemText.Y+cgoItemText.Hgt-1-::GraphicsResource.FontRegular.GetLineHeight(), C4Draw::DEFAULT_MESSAGE_COLOR, ARight);
197  }
198 }
199 
200 void C4MenuItem::MouseInput(C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
201 {
202  // clicky clicky!
203  if (iButton == C4MC_Button_LeftDown)
204  {
205  // button down: Init drag only; Enter selection only by button up
206  if (IsDragElement())
207  StartDragging(rMouse, iX, iY, dwKeyParam);
208  }
209  else if (iButton == C4MC_Button_LeftUp)
210  {
211  // left-click performed
212  pMenu->UserEnter(::MouseControl.GetPlayer(), this, false);
213  return;
214  }
215  else if (iButton == C4MC_Button_RightUp)
216  {
217  // right-up: Alternative enter command
218  pMenu->UserEnter(::MouseControl.GetPlayer(), this, true);
219  return;
220  }
221  // inherited; this is just setting some vars
222  typedef C4GUI::Element ParentClass;
223  ParentClass::MouseInput(rMouse, iButton, iX, iY, dwKeyParam);
224 }
225 
227 {
228  // callback to menu: Select item
230  typedef C4GUI::Element ParentClass;
231  ParentClass::MouseEnter(rMouse);
232 }
233 
234 // -----------------------------------------------------------
235 // C4Menu
236 
237 C4Menu::C4Menu() : C4GUI::Dialog(100, 100, nullptr, true) // will be re-adjusted later
238 {
239  Default();
241  // initially invisible: Will be made visible at first drawing by viewport
242  // when the location will be inialized
243  SetVisibility(false);
244 }
245 
247 {
248  Selection=-1;
250  ItemCount=0;
252  NeedRefill=false;
253  Symbol.Default();
254  Caption[0]=0;
255  Permanent=false;
257  ExtraData=0;
258  TimeOnSelection=0;
259  Identification=0;
260  LocationSet=false;
261  Columns=Lines=0;
263  VisibleCount=0;
264  fHasPortrait = false;
265  fTextProgressing = false;
266  fEqualIconItemHeight = false;
268  fActive = false;
269 }
270 
272 {
273  Close(false);
274  Symbol.Clear();
275  ClearItems();
276  ClearFrameDeco();
277  fActive = false;
278 }
279 
280 bool C4Menu::TryClose(bool fOK, bool fControl)
281 {
282  // abort if menu is permanented by script
283  if (!fOK) if (IsCloseDenied()) return false;
284 
285  // close the menu
286  Close(fOK);
287  Clear();
288  ::pGUI->RemoveElement(this);
289 
290  // invoke close command
291  if (fControl && CloseCommand.getData())
292  {
294  }
295 
296  // done
297  return true;
298 }
299 
300 bool C4Menu::DoInit(C4FacetSurface &fctSymbol, const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
301 {
302  Clear(); Default();
303  Symbol.GrabFrom(fctSymbol);
304  return InitMenu(szEmpty, iExtra, iExtraData, iId, iStyle);
305 }
306 
307 bool C4Menu::DoInitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
308 {
309  Clear(); Default();
310  Symbol.Set(fctSymbol);
311  return InitMenu(szEmpty, iExtra, iExtraData, iId, iStyle);
312 }
313 
314 bool C4Menu::InitMenu(const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
315 {
316  SCopy(szEmpty,Caption,C4MaxTitle);
317  Extra=iExtra; ExtraData=iExtraData;
318  Identification=iId;
319  if (*Caption || iStyle == C4MN_Style_Dialog) SetTitle(Caption, HasMouse()); else SetTitle(" ", HasMouse());
320  if (pTitle) pTitle->SetIcon(Symbol);
321  Style=iStyle & C4MN_Style_BaseMask;
322  // Menus are synchronous to allow COM_MenuUp/Down to be converted to movements at the clients
323  if (Style == C4MN_Style_Normal)
324  Columns = 5;
325  else
326  // in reality, Dialog menus may have two coloumns (first for the portrait)
327  // however, they are not uniformly spaced and stuff; so they are better just ignored and handled by the drawing routine
328  Columns=1;
331  ::pGUI->ShowDialog(this, false);
332  fTextProgressing = false;
333  fActive = true;
334  return true;
335 }
336 
337 bool C4Menu::AddRefSym(const char *szCaption, const C4Facet &fctSymbol, const char *szCommand,
338  int32_t iCount, C4Object *pObject, const char *szInfoCaption,
339  C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
340 {
341  if (!IsActive()) return false;
342  // Create new menu item
343  C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
344  // Ref Symbol
345  pNew->RefSymbol(fctSymbol);
346  // Add
347  return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
348 }
349 
350 bool C4Menu::Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand,
351  int32_t iCount, C4Object *pObject, const char *szInfoCaption,
352  C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
353 {
354  if (!IsActive()) return false;
355  // Create new menu item
356  C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
357  // Set Symbol
358  pNew->GrabSymbol(fctSymbol);
359  // Add
360  return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
361 }
362 
363 bool C4Menu::Add(const char *szCaption, C4Object* pGfxObj, const char *szCommand,
364  int32_t iCount, C4Object *pObject, const char *szInfoCaption,
365  C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
366 {
367  if (!IsActive()) return false;
368  // Create new menu item
369  C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
370  // Set Symbol
371  pNew->SetGraphics(pGfxObj);
372  // Add
373  return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
374 }
375 
376 bool C4Menu::Add(const char *szCaption, C4DefGraphics* pGfx, const char *szCommand,
377  int32_t iCount, C4Object *pObject, const char *szInfoCaption,
378  C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
379 {
380  if (!IsActive()) return false;
381  // Create new menu item
382  C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
383  // Set Symbol
384  pNew->SetGraphics(pGfx);
385  // Add
386  return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
387 }
388 
389 bool C4Menu::AddItem(C4MenuItem *pNew, const char *szCaption, const char *szCommand,
390  int32_t iCount, C4Object *pObject, const char *szInfoCaption,
391  C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
392 {
394  if (pObject)
395  {
396  C4RCMenuAdd rc = { pObject ? pObject->Number : -1, iCount, idID, fOwnValue, iValue, fIsSelectable };
397  AddDbgRec(RCT_MenuAdd, &rc, sizeof(C4RCMenuAdd));
398  if (szCommand) AddDbgRec(RCT_MenuAddC, szCommand, strlen(szCommand)+1);
399  if (szCommand2) AddDbgRec(RCT_MenuAddC, szCommand2, strlen(szCommand2)+1);
400  }
401  // Add it to the list
402  pClientWindow->AddElement(pNew);
403  // first menuitem is portrait, if it does not have text but a facet
404  if (!ItemCount && (!szCaption || !*szCaption))
405  fHasPortrait = true;
406  // Item count
407  ItemCount++;
408  // set new item size
410  // Init selection if not frozen
411  if (Selection==-1 && fIsSelectable && !pClientWindow->IsFrozen()) SetSelection(ItemCount-1, false, false);
412  // initial progress
413  if (fTextProgressing) pNew->TextDisplayProgress = 0;
414  // adjust scrolling, etc.
415  UpdateScrollBar();
416  // Success
417  return true;
418 }
419 
420 bool C4Menu::Control(BYTE byCom, int32_t iData)
421 {
422  if (!IsActive()) return false;
423 
424  switch (byCom)
425  {
426  case COM_MenuEnter: Enter(); break;
427  case COM_MenuEnterAll: Enter(true); break;
428  case COM_MenuClose: TryClose(false, true); break;
429 
430  // organize with nicer subfunction...
431  case COM_MenuLeft:
432  // Top wrap-around
433  if (Selection-1 < 0)
434  MoveSelection(ItemCount - 1 - Selection, true, true);
435  else
436  MoveSelection(-1, true, true);
437  break;
438  case COM_MenuRight:
439  // Bottom wrap-around
440  if (Selection+1 >= ItemCount)
441  MoveSelection(-Selection, true, true);
442  else
443  MoveSelection(+1, true, true);
444  break;
445  case COM_MenuUp:
446  iData = -Columns;
447  // Top wrap-around
448  if (Selection + iData < 0)
449  while (Selection + iData + Columns < ItemCount)
450  iData += Columns;
451  MoveSelection(iData, true, true);
452  break;
453  case COM_MenuDown:
454  iData = +Columns;
455  // Bottom wrap-around
456  if (Selection+iData >= ItemCount)
457  while (Selection+iData-Columns >= 0)
458  iData-=Columns;
459  MoveSelection(iData, true, true);
460  break;
461  case COM_MenuSelect:
462  if (ItemCount)
463  SetSelection(iData & (~C4MN_AdjustPosition), !!(iData & C4MN_AdjustPosition), true);
464  break;
465  case COM_MenuShowText:
466  SetTextProgress(-1, false);
467  break;
468  }
469 
470  return true;
471 }
472 
474 {
475  // direct keyboard callback
476  if (!IsActive()) return false;
477  return !!Control(byCom, 0);
478 }
479 
481 {
482  return fActive;
483 }
484 
485 bool C4Menu::Enter(bool fRight)
486 {
487  // Not active
488  if (!IsActive()) return false;
489  if (Style==C4MN_Style_Info) return false;
490  // Get selected item
491  C4MenuItem *pItem = GetSelectedItem();
492  if (!pItem)
493  {
494  // okay for dialogs: Just close them
495  if (Style == C4MN_Style_Dialog) TryClose(false, true);
496  return true;
497  }
498  // Copy command to buffer (menu might be cleared)
499  char szCommand[_MAX_FNAME_LEN+30];
500  SCopy(pItem->Command,szCommand);
501  if (fRight && pItem->Command2[0]) SCopy(pItem->Command2,szCommand);
502 
503  // Close if not permanent
504  if (!Permanent) { Close(true); fActive = false; }
505 
506  // exec command (note that menu callback may delete this!)
507  MenuCommand(szCommand, false);
508 
509  return true;
510 }
511 
512 C4MenuItem* C4Menu::GetItem(int32_t iIndex)
513 {
514  return static_cast<C4MenuItem *>(pClientWindow->GetElementByIndex(iIndex));
515 }
516 
518 {
519  return ItemCount;
520 }
521 
522 bool C4Menu::MoveSelection(int32_t iBy, bool fAdjustPosition, bool fDoCalls)
523 {
524  if (!iBy) return false;
525  // find next item that can be selected by moving in iBy steps
526  int32_t iNewSel = Selection;
527  for (;;)
528  {
529  // determine new selection
530  iNewSel += iBy;
531  // selection is out of menu range
532  if (!Inside<int32_t>(iNewSel, 0, ItemCount-1)) return false;
533  // determine newly selected item
534  C4MenuItem *pNewSel = GetItem(iNewSel);
535  // nothing selectable
536  if (!pNewSel || !pNewSel->IsSelectable) continue;
537  // got something: go select it
538  break;
539  }
540  // select it
541  return !!SetSelection(iNewSel, fAdjustPosition, fDoCalls);
542 }
543 
544 bool C4Menu::SetSelection(int32_t iSelection, bool fAdjustPosition, bool fDoCalls)
545 {
546  // Not active
547  if (!IsActive()) return false;
548  // Outside Limits / Selectable
549  C4MenuItem *pNewSel = GetItem(iSelection);
550  if ((iSelection==-1 && !ItemCount) || (pNewSel && pNewSel->IsSelectable))
551  {
552  // Selection change
553  if (iSelection!=Selection)
554  {
555  // calls
556  C4MenuItem *pSel = GetSelectedItem();
557  if (pSel) pSel->SetSelected(false);
558  // Set selection
559  Selection=iSelection;
560  // Reset time on selection
561  TimeOnSelection=0;
562  }
563  // always recheck selection for internal refill
564  C4MenuItem *pSel = GetSelectedItem();
565  if (pSel) pSel->SetSelected(true);
566  // set main caption by selection
567  if (Style == C4MN_Style_Normal)
568  {
569  if (pSel)
570  SetTitle(*(pSel->Caption) ? pSel->Caption : " ", HasMouse());
571  else
572  SetTitle(*Caption ? Caption : " ", HasMouse());
573  }
574  }
575  // adjust position, if desired
576  if (fAdjustPosition) AdjustPosition();
577  // do selection callback
578  if (fDoCalls) OnSelectionChanged(Selection);
579  // Done
580  return true;
581 }
582 
584 {
585  return GetItem(Selection);
586 }
587 
589 {
590  // Adjust position by selection (works only after InitLocation)
591  if ((Lines > 1) && Columns)
592  {
593  C4MenuItem *pSel = GetSelectedItem();
594  if (pSel)
596  }
597 }
598 
600 {
601  return Selection;
602 }
603 
604 bool C4Menu::SetPosition(int32_t iPosition)
605 {
606  if (!IsActive()) return false;
607  // update scroll pos, if location is initialized
609  return true;
610 }
611 
613 {
614  return Identification;
615 }
616 
617 void C4Menu::SetSize(int32_t iToWdt, int32_t iToHgt)
618 {
619  if (iToWdt) Columns=iToWdt;
620  if (iToHgt) Lines=iToHgt;
621  InitSize();
622 }
623 
625 {
626 
627  // Item size by style
628  switch (Style)
629  {
630  case C4MN_Style_Normal:
632  break;
633  case C4MN_Style_Context:
634  {
636  int32_t iWdt, iHgt;
638  // FIXME: Blah. This stuff should be calculated correctly by pTitle.
639  ItemWidth += ItemHeight + 16;
640  C4MenuItem *pItem;
641  for (int i = 0; (pItem = GetItem(i)); ++i)
642  {
643  ::GraphicsResource.FontRegular.GetTextExtent(pItem->Caption, iWdt, iHgt, true);
644  ItemWidth = std::max(ItemWidth, iWdt + pItem->GetSymbolWidth(ItemHeight));
645  }
646  ItemWidth += 3; // Add some extra space so text doesn't touch right border frame...
647  break;
648  }
649  case C4MN_Style_Info:
650  {
651  // calculate size from a default size determined by a window width of C4MN_DefInfoWdt
652  int32_t iWdt,iHgt,iLargestTextWdt;
654  iLargestTextWdt = iWdt + 2 * C4MN_SymbolSize + C4MN_FrameWidth;
655  ItemWidth=std::min<int>(cgoArea.Wdt - 2*C4MN_FrameWidth, std::max(iLargestTextWdt, C4MN_DefInfoWdt));
656  ItemHeight=0;
657  StdStrBuf sText;
658  C4MenuItem *pItem;
659  for (int32_t i=0; (pItem=GetItem(i)); ++i)
660  {
662  ::GraphicsResource.FontRegular.GetTextExtent(sText.getData(),iWdt,iHgt, true);
663  assert(iWdt <= ItemWidth);
664  ItemWidth=std::max(ItemWidth,iWdt); ItemHeight=std::max(ItemHeight,iHgt);
665  iLargestTextWdt = std::max(iLargestTextWdt, iWdt);
666  }
667  // although width calculation is done from C4MN_DefInfoWdt, this may be too large for some very tiny info windows
668  // so make sure no space is wasted
669  ItemWidth = std::min(ItemWidth, iLargestTextWdt);
670  // Add some extra space so text doesn't touch right border frame...
671  ItemWidth += 3;
672  // Now add some space to show the picture on the left
674  // And set a minimum item height (again, for the picture)
675  ItemHeight = std::max<int>(ItemHeight, C4PictureSize);
676  break;
677  }
678 
679  case C4MN_Style_Dialog:
680  {
681  // dialog window: Item width is whole dialog, portrait subtracted if any
682  // Item height varies
683  int32_t iWdt,iHgt;
685  ItemWidth=std::min<int>(cgoArea.Wdt - 2*C4MN_FrameWidth, std::max<int>(iWdt + 2 * C4MN_SymbolSize + C4MN_FrameWidth, C4MN_DlgWdt));
686  ItemHeight=iHgt; // Items may be multiline and higher
687  if (HasPortrait())
688  {
689  // subtract portrait only if this would not make the dialog too small
690  if (ItemWidth > C4MN_DlgPortraitWdt*2 && cgoArea.Hgt > cgoArea.Wdt)
692  }
693  }
694  }
695 
696  int DisplayedItemCount = ItemCount - HasPortrait();
697  if (Style == C4MN_Style_Dialog)
699  else
700  Lines = DisplayedItemCount/Columns+std::min<int32_t>(DisplayedItemCount%Columns,1);
701  // adjust by max. height
702  Lines=std::max<int32_t>(std::min<int32_t>((cgoArea.Hgt-100)/std::max<int32_t>(ItemHeight,1),Lines),1);
703 
704  InitSize();
705  int32_t X,Y;
707  {
708  X = rcBounds.x;
709  Y = rcBounds.y;
710  }
711  else
712  {
713  X = (cgoArea.Wdt - rcBounds.Wdt)/2;
714  Y = (cgoArea.Hgt - rcBounds.Hgt)/2;
715  }
716  // Alignment
721  if (Alignment & C4MN_Align_Free) { X=Clamp<int32_t>(X,0,cgoArea.Wdt-rcBounds.Wdt); Y=Clamp<int32_t>(Y,0,cgoArea.Hgt-rcBounds.Hgt); }
722  // Centered (due to small viewport size)
723  if (rcBounds.Wdt>cgoArea.Wdt-2*C4SymbolSize) X=(cgoArea.Wdt-rcBounds.Wdt)/2;
724  if (rcBounds.Hgt>cgoArea.Hgt-2*C4SymbolSize) Y=(cgoArea.Hgt-rcBounds.Hgt)/2;
725  SetPos(X, Y);
726 
727  // Position initialized: Make it visible to be used!
728  SetVisibility(true);
729 
730  // now align all menu items correctly
732 
733  // and correct scroll pos
734  UpdateScrollBar();
735  AdjustPosition();
736 }
737 
738 
740 {
742  // Size calculation
743  int Width, Height;
744  Width=Columns*ItemWidth;
745  Height=Lines*ItemHeight;
747  bool fBarNeeded;
749  // dialogs have auto-enlarge vertically
750  if (pLast && Style == C4MN_Style_Dialog)
751  {
752  Height = std::max<int>(Height, pLast->GetBounds().y + pLast->GetBounds().Hgt + C4MN_DlgLineMargin);
753  fBarNeeded = false;
754  }
755  else
756  fBarNeeded = pLast && pLast->GetBounds().y + pLast->GetBounds().Hgt > pClientWindow->GetBounds().Hgt;
757  // add dlg margins
760  if (fBarNeeded) Width += C4GUI_ScrollBarWdt;
761  SetBounds(C4Rect(rcBounds.x, rcBounds.y, Width, Height));
762  pClientWindow->SetScrollBarEnabled(fBarNeeded);
763  UpdateOwnPos();
764 }
765 
767 {
769  bool fBarNeeded = pLast && pLast->GetBounds().y + pLast->GetBounds().Hgt > pClientWindow->GetBounds().Hgt;
770  if (pClientWindow->IsScrollBarEnabled() == fBarNeeded) return;
771  // resize for bar
772  InitSize();
773 }
774 
776 {
777  // Inactive
778  if (!IsActive()) return;
779 
780  // Location
781  if (!LocationSet) { InitLocation(cgo); LocationSet=true; }
782 
783  // If drawn by a viewport, then it's made visible
784  SetVisibility(true);
785 
786  // do drawing
787  typedef C4GUI::Dialog ParentClass;
788  ParentClass::Draw(cgo);
789 
790  // draw tooltip if selection time has been long enough
793  if (Style != C4MN_Style_Info) // No tooltips in info menus - doesn't make any sense...
794  if (!::Control.isReplay())
795  if (!::pGUI->Mouse.IsActiveInput())
796  {
797  C4MenuItem *pSel = GetSelectedItem();
798  if (pSel && *pSel->InfoCaption)
799  {
800  int32_t iX=0, iY=0;
801  pSel->ClientPos2ScreenPos(iX, iY);
802  C4GUI::Screen::DrawToolTip(pSel->InfoCaption, cgo, iX, iY);
803  }
804  }
805 }
806 
807 
809 {
810  // inherited (background)
811  typedef C4GUI::Dialog ParentClass;
812  ParentClass::DrawElement(cgo);
813 
814  // Get selected item id
815  C4ID idSelected; C4MenuItem *pItem;
816  if ((pItem = GetSelectedItem())) idSelected = pItem->id; else idSelected = C4ID::None;
817  C4Def *pDef = C4Id2Def(idSelected);
818  // Get item value
819  int32_t iValue = 0;
820  if (pDef)
821  {
822  if (pItem && pItem->fOwnValue)
823  iValue = pItem->iValue;
824  else
825  iValue = pDef->GetValue(nullptr, NO_OWNER);
826  }
827 
828  // Store and clear global clipper
829 // int32_t iX1,iY1,iX2,iY2;
830 // pDraw->GetPrimaryClipper(iX1,iY1,iX2,iY2);
831 // pDraw->SubPrimaryClipper(rcBounds.x, rcBounds.y, rcBounds.x+rcBounds.Wdt-1, rcBounds.y+rcBounds.Hgt-1);
832 
834 
835  // Draw bar divider
836  if (Extra)
837  {
838  DrawFrame(cgoExtra.Surface, cgoExtra.X-1, cgoExtra.Y-1, cgoExtra.Wdt+1, cgoExtra.Hgt+1);
839  }
840 
841  // Draw specified extra
842  switch (Extra)
843  {
844  case C4MN_Extra_Value:
845  {
846  if (pDef) ::GraphicsResource.fctWealth.DrawValue(cgoExtra,iValue,0,0,C4FCT_Right);
847  }
848  break;
849  }
850 }
851 
852 void C4Menu::DrawFrame(C4Surface * sfcSurface, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
853 {
854  pDraw->DrawFrameDw(sfcSurface, iX+1, iY+1, iX+iWdt-1,iY+iHgt-1, C4RGB(0x44, 0, 0));
855 }
856 
857 void C4Menu::SetAlignment(int32_t iAlignment)
858 {
859  Alignment = iAlignment;
860 }
861 
862 void C4Menu::SetPermanent(bool fPermanent)
863 {
864  Permanent = fPermanent;
865 }
866 
868 {
869  // Reset flag
870  NeedRefill=false;
871 
872  // do the refill in frozen window (no scrolling update)
873  int32_t iLastItemCount=ItemCount;
874  bool fRefilled = false;
876  bool fSuccess = DoRefillInternal(fRefilled);
879  if (!fSuccess) return false;
880 
881  // menu contents may have changed: Adjust menu size and selection
882  if (fRefilled)
883  {
884  // Adjust selection
885  AdjustSelection();
886  // Item count increased: resize
887  if (ItemCount > iLastItemCount) LocationSet = false;
888  // Item count decreased: resize if we are a context menu
889  if ((ItemCount < iLastItemCount) && IsContextMenu()) LocationSet = false;
890  }
891  // Success
892  return true;
893 }
894 
896 {
897  C4MenuItem *pItem;
898  while ((pItem = GetItem(0))) delete pItem;
899  ItemCount=0;
900  UpdateScrollBar();
901 }
902 
904 {
905  if (!IsActive()) return;
906  // Refill (timer or flag)
907  if (!Game.iTick35 || NeedRefill)
908  if (!RefillInternal())
909  Close(false);
910  // text progress
911  if (fTextProgressing)
912  SetTextProgress(+1, true);
913 }
914 
916 {
917  if (!IsActive()) return false;
918  // Refill (close if failure)
919  if (!RefillInternal())
920  { Close(false); return false; }
921  // Success
922  return true;
923 }
924 
926 {
927  // selection valid?
928  C4MenuItem *pSelection = GetItem(Selection);
929  int iSel = Selection;
930  if (!pSelection || !pSelection->IsSelectable)
931  {
932  // set to new first valid selection: Downwards first
933  iSel = Selection;
934  while (--iSel>=0)
935  if ((pSelection = GetItem(iSel)))
936  if (pSelection->IsSelectable)
937  break;
938  // no success: upwards then
939  if (iSel<0)
940  for (iSel=Selection+1; (pSelection = GetItem(iSel)); ++iSel)
941  if (pSelection->IsSelectable)
942  break;
943  }
944  // set it then
945  if (!pSelection)
946  SetSelection(-1, Selection >= 0, false);
947  else
948  SetSelection(iSel, iSel != Selection, true);
949 }
950 
951 bool C4Menu::SetLocation(int32_t iX, int32_t iY)
952 {
953  // just set position...
954  SetPos(iX, iY);
955  return true;
956 }
957 
958 bool C4Menu::SetTextProgress(int32_t iToProgress, bool fAdd)
959 {
960  // menu active at all?
961  if (!IsActive()) return false;
962  // set: enable or disable progress?
963  if (!fAdd)
964  fTextProgressing = (iToProgress >= 0);
965  else
966  {
967  // add: Does not enable progressing
968  if (!fTextProgressing) return false;
969  }
970  // update menu items
971  C4MenuItem *pItem;
972  bool fAnyItemUnfinished = false;
973  for (int32_t i=HasPortrait(); (pItem = GetItem(i)); ++i)
974  {
975  // disabled progress: set all progresses to shown
976  if (!fTextProgressing)
977  {
978  pItem->TextDisplayProgress = -1;
979  continue;
980  }
981  // do progress on item, if any is left
982  // this call automatically reduces iToProgress as it's used up
983  if (!fAdd) pItem->TextDisplayProgress = 0;
984  if (iToProgress) pItem->DoTextProgress(iToProgress);
985  if (pItem->TextDisplayProgress > -1) fAnyItemUnfinished = true;
986  }
987  // if that progress showed everything already, mark as not progressing
988  fTextProgressing = fAnyItemUnfinished;
989  // done, success
990  return true;
991 }
992 
994 {
995  // ask all viewports
996  for (C4Viewport *pVP = ::Viewports.GetFirstViewport(); pVP; pVP = pVP->GetNext())
997  if (pVP->IsViewportMenu(this))
998  return pVP;
999  // none matching
1000  return nullptr;
1001 }
1002 
1004 {
1005  // only if already shown and made visible by first drawing
1006  // this will postpone the call of menu initialization until it's really needed
1007  if (!IsVisible() || !pClientWindow) return;
1008  // reposition client scrolling window
1010  // re-stack all list items
1011  int xOff, yOff = 0;
1012  C4MenuItem *pCurr = static_cast<C4MenuItem *>(pClientWindow->GetFirst()), *pPrev = nullptr;
1013  if (HasPortrait() && pCurr)
1014  {
1015  // recheck portrait
1017  C4Facet &fctPortrait = pCurr->Symbol;
1018  C4Rect rcPortraitBounds(0,0, C4MN_DlgPortraitWdt + C4MN_DlgPortraitIndent, fctPortrait.Hgt * C4MN_DlgPortraitWdt / std::max<int>(fctPortrait.Wdt, 1));
1019  if (pCurr->GetBounds() != rcPortraitBounds)
1020  {
1021  pCurr->GetBounds() = rcPortraitBounds;
1022  pCurr->UpdateOwnPos();
1023  }
1024  pCurr = static_cast<C4MenuItem *>(pCurr->GetNext());
1025  }
1026  else xOff = 0;
1027  // recheck list items
1028  int32_t iMaxDlgOptionHeight = -1;
1029  int32_t iIndex = 0; C4Rect rcNewBounds(0,0,ItemWidth,ItemHeight);
1030  C4MenuItem *pFirstStack = pCurr, *pNext = pFirstStack;
1031  while ((pCurr = pNext))
1032  {
1033  pNext = static_cast<C4MenuItem *>(pCurr->GetNext());
1034  if (Style == C4MN_Style_Dialog)
1035  {
1036  // y-margin always, except between options
1037  if (!pPrev || (!pPrev->IsSelectable || !pCurr->IsSelectable)) yOff += C4MN_DlgLineMargin; else yOff += C4MN_DlgOptionLineMargin;
1038  // determine item height.
1039  StdStrBuf sText;
1040  int32_t iAssumedItemHeight = ::GraphicsResource.FontRegular.GetLineHeight();
1041  int32_t iWdt, iAvailWdt = ItemWidth, iSymWdt;
1042  for (;;)
1043  {
1044  iSymWdt = std::min<int32_t>(pCurr->GetSymbolWidth(iAssumedItemHeight), iAvailWdt/2);
1045  iAvailWdt = ItemWidth - iSymWdt;
1046  ::GraphicsResource.FontRegular.BreakMessage(pCurr->Caption, iAvailWdt, &sText, true);
1047  ::GraphicsResource.FontRegular.GetTextExtent(sText.getData(),iWdt,rcNewBounds.Hgt, true);
1048  if (!iSymWdt || rcNewBounds.Hgt <= iAssumedItemHeight) break;
1049  // If there is a symbol, the symbol grows as more lines become available
1050  // Thus, less space is available for the text, and it might become larger
1051  iAssumedItemHeight = rcNewBounds.Hgt;
1052  }
1053  if (fEqualIconItemHeight && iSymWdt)
1054  {
1055  // force equal height for all symbol items
1056  if (iMaxDlgOptionHeight < 0)
1057  {
1058  // first selectable item inits field
1059  iMaxDlgOptionHeight = rcNewBounds.Hgt;
1060  }
1061  else if (rcNewBounds.Hgt <= iMaxDlgOptionHeight)
1062  {
1063  // following item height smaller or equal: Force equal
1064  rcNewBounds.Hgt = iMaxDlgOptionHeight;
1065  }
1066  else
1067  {
1068  // following item larger height: Need to re-stack from beginning
1069  iMaxDlgOptionHeight = rcNewBounds.Hgt;
1070  pNext = pFirstStack;
1071  pPrev = nullptr;
1072  yOff = 0;
1073  iIndex = 0;
1074  continue;
1075  }
1076  }
1077  assert(iWdt <= iAvailWdt);
1078  rcNewBounds.x = 0;
1079  rcNewBounds.y = yOff;
1080  yOff += rcNewBounds.Hgt;
1081  }
1082  else
1083  {
1084  rcNewBounds.x = (iIndex % std::max<int32_t>(Columns, 1)) * ItemWidth;
1085  rcNewBounds.y = (iIndex / std::max<int32_t>(Columns, 1)) * ItemHeight;
1086  }
1087  rcNewBounds.x += xOff;
1088  if (pCurr->GetBounds() != rcNewBounds)
1089  {
1090  pCurr->GetBounds() = rcNewBounds;
1091  pCurr->UpdateOwnPos();
1092  }
1093  ++iIndex;
1094  pPrev = pCurr;
1095  }
1096  // update scrolling
1097  pClientWindow->SetClientHeight(rcNewBounds.y + rcNewBounds.Hgt);
1098  // re-set caption
1099  C4MenuItem *pSel = GetSelectedItem();
1100  const char *szCapt;
1101  if (pSel && Style == C4MN_Style_Normal)
1102  szCapt = pSel->Caption;
1103  else
1104  szCapt = Caption;
1105  SetTitle((*szCapt || Style == C4MN_Style_Dialog) ? szCapt : " ", HasMouse());
1106 }
1107 
1109 {
1110  // client rect and stuff
1111  typedef C4GUI::Dialog ParentClass;
1112  ParentClass::UpdateOwnPos();
1114 }
1115 
1116 void C4Menu::UserSelectItem(int32_t Player, C4MenuItem *pItem)
1117 {
1118  // not if user con't control anything
1119  if (IsReadOnly()) return;
1120  // the item must be selectable
1121  if (!pItem || !pItem->IsSelectable) return;
1122  // queue or direct selection
1123  OnUserSelectItem(Player, pItem->iIndex);
1124 }
1125 
1126 void C4Menu::UserEnter(int32_t Player, C4MenuItem *pItem, bool fRight)
1127 {
1128  // not if user con't control anything
1129  if (IsReadOnly()) return;
1130  // the item must be selectable
1131  if (!pItem || !pItem->IsSelectable) return;
1132  // queue or direct enter
1133  OnUserEnter(Player, pItem->iIndex, fRight);
1134 }
1135 
1136 void C4Menu::UserClose(bool fOK)
1137 {
1138  // not if user con't control anything
1139  if (IsReadOnly()) return;
1140  // queue or direct enter
1141  OnUserClose();
1142 }
1143 
1144 void C4Menu::SetCloseCommand(const char *strCommand)
1145 {
1146  CloseCommand.Copy(strCommand);
1147 }
1148 
1150 {
1151  int32_t iPlayer = GetControllingPlayer();
1152  if (iPlayer == NO_OWNER) return true; // free view dialog also has the mouse
1153  C4Player *pPlr = ::Players.Get(iPlayer);
1154  if (pPlr && pPlr->MouseControl) return true;
1155  return false;
1156 }
1157 
1159 {
1160  C4MenuItem *pItem;
1161  for (int32_t i=0; (pItem = GetItem(i)); ++i)
1162  pItem->ClearPointers(pObj);
1163 }
1164 
1165 #ifdef _DEBUG
1166 void C4Menu::AssertSurfaceNotUsed(C4Surface *sfc)
1167 {
1168  C4MenuItem *pItem;
1169  if (!sfc) return;
1170  assert(sfc != Symbol.Surface);
1171  for (int32_t i=0; (pItem = GetItem(i)); ++i)
1172  assert(pItem->Symbol.Surface != sfc) ;
1173 }
1174 #endif
#define X(sdl, oc)
C4Object * Object(C4PropList *_this)
Definition: C4AulDefFunc.h:34
C4Config Config
Definition: C4Config.cpp:930
const BYTE COM_MenuSelect
Definition: C4Constants.h:132
const int C4PictureSize
Definition: C4Constants.h:60
const BYTE COM_MenuLeft
Definition: C4Constants.h:128
const size_t C4MaxTitle
Definition: C4Constants.h:25
const BYTE COM_MenuUp
Definition: C4Constants.h:130
const int C4SymbolSize
Definition: C4Constants.h:58
const BYTE COM_MenuClose
Definition: C4Constants.h:126
const BYTE COM_MenuRight
Definition: C4Constants.h:129
const BYTE COM_MenuDown
Definition: C4Constants.h:131
const BYTE COM_MenuEnterAll
Definition: C4Constants.h:125
const BYTE COM_MenuEnter
Definition: C4Constants.h:124
const BYTE COM_MenuShowText
Definition: C4Constants.h:127
const int NO_OWNER
Definition: C4Constants.h:137
C4Def * C4Id2Def(C4ID id)
Definition: C4DefList.h:84
C4Draw * pDraw
Definition: C4Draw.cpp:42
const int32_t C4FCT_Right
Definition: C4Facet.h:28
const int32_t C4FCT_Left
Definition: C4Facet.h:27
C4Game Game
Definition: C4Globals.cpp:52
C4MouseControl MouseControl
Definition: C4Globals.cpp:47
C4GraphicsResource GraphicsResource
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
#define C4GUI_ScrollBarWdt
Definition: C4Gui.h:103
constexpr bool DEBUGREC_MENU
Definition: C4Include.h:34
const int32_t C4MN_InfoCaption_Delay
Definition: C4Menu.cpp:43
const int32_t C4MN_DlgLineMargin
Definition: C4Menu.cpp:38
const int32_t C4MN_DefInfoWdt
Definition: C4Menu.cpp:35
const int32_t C4MN_DlgPortraitIndent
Definition: C4Menu.cpp:41
const int32_t C4MN_DlgLines
Definition: C4Menu.cpp:37
const int32_t C4MN_DlgWdt
Definition: C4Menu.cpp:36
const int32_t C4MN_DlgPortraitWdt
Definition: C4Menu.cpp:40
const int32_t C4MN_DlgOptionLineMargin
Definition: C4Menu.cpp:39
@ C4MN_Extra_Value
Definition: C4Menu.h:45
@ C4MN_Extra_None
Definition: C4Menu.h:44
@ C4MN_Item_NoCount
Definition: C4Menu.h:58
@ C4MN_Style_Dialog
Definition: C4Menu.h:38
@ C4MN_Style_Normal
Definition: C4Menu.h:35
@ C4MN_Style_Context
Definition: C4Menu.h:36
@ C4MN_Style_BaseMask
Definition: C4Menu.h:39
@ C4MN_Style_Info
Definition: C4Menu.h:37
@ C4MN_Style_EqualItemHeight
Definition: C4Menu.h:40
@ C4MN_Align_Left
Definition: C4Menu.h:50
@ C4MN_Align_Right
Definition: C4Menu.h:51
@ C4MN_Align_Free
Definition: C4Menu.h:54
@ C4MN_Align_Top
Definition: C4Menu.h:52
@ C4MN_Align_Bottom
Definition: C4Menu.h:53
@ C4MN_FrameWidth
Definition: C4Menu.h:31
@ C4MN_SymbolSize
Definition: C4Menu.h:30
@ C4MN_AdjustPosition
Definition: C4Menu.h:62
const int32_t C4MC_Button_RightUp
const int32_t C4MC_Button_LeftUp
const int32_t C4MC_Button_LeftDown
C4PlayerList Players
void AddDbgRec(C4RecordChunkType eType, const void *pData, int iSize)
Definition: C4Record.cpp:32
@ RCT_MenuAdd
Definition: C4Record.h:81
@ RCT_MenuAddC
Definition: C4Record.h:82
const int ARight
Definition: C4Surface.h:41
const int ALeft
Definition: C4Surface.h:41
C4ViewportList Viewports
#define _MAX_FNAME
#define _MAX_FNAME_LEN
uint8_t BYTE
uint32_t DWORD
void SReplaceChar(char *str, char fc, char tc)
Definition: Standard.cpp:354
int SCharPos(char cTarget, const char *szInStr, int iIndex)
Definition: Standard.cpp:239
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
uint32_t GetNextCharacter(const char **pszString)
Definition: Standard.h:84
#define sprintf
Definition: Standard.h:162
#define C4RGB(r, g, b)
Definition: StdColors.h:26
int32_t DebugRec
Definition: C4Config.h:63
C4ConfigGeneral General
Definition: C4Config.h:255
void Draw(C4Facet &cgo, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *trans)
Definition: C4Def.h:99
int32_t Constructable
Definition: C4Def.h:118
int32_t GetValue(C4Object *pInBase, int32_t iBuyPlayer)
Definition: C4Def.cpp:621
bool SubPrimaryClipper(int iX1, int iY1, int iX2, int iY2)
Definition: C4Draw.cpp:196
void DrawFrameDw(C4Surface *sfcDest, int x1, int y1, int x2, int y2, DWORD dwClr, float width=1.0f)
Definition: C4Draw.cpp:635
bool RestorePrimaryClipper()
Definition: C4Draw.cpp:210
@ DEFAULT_MESSAGE_COLOR
Definition: C4Draw.h:167
void DrawBoxDw(C4Surface *sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr)
Definition: C4Draw.cpp:840
bool StorePrimaryClipper()
Definition: C4Draw.cpp:203
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:561
C4Surface * Surface
Definition: C4Facet.h:117
float Hgt
Definition: C4Facet.h:118
void DrawValue(C4Facet &cgo, int32_t iValue, int32_t iPhaseX=0, int32_t iPhaseY=0, int32_t iAlign=C4FCT_Center)
Definition: C4Facet.cpp:308
void DrawClr(C4Facet &cgo, bool fAspect=true, DWORD dwClr=0)
Definition: C4Facet.cpp:213
C4Facet Truncate(int32_t iAlign, int32_t iSize)
Definition: C4Facet.cpp:284
float Wdt
Definition: C4Facet.h:118
float Y
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
void Clear()
Definition: C4FacetEx.h:44
void GrabFrom(C4FacetSurface &rSource)
Definition: C4FacetEx.h:57
void Set(const C4Facet &cpy)
Definition: C4FacetEx.h:46
void Default()
Definition: C4FacetEx.h:43
bool IsActiveInput()
Definition: C4Gui.h:2581
void AddElement(Element *pChild)
Element * GetElementByIndex(int32_t i)
Element * pLast
Definition: C4Gui.h:750
Element * GetFirst()
Definition: C4Gui.h:829
void SetVisibility(bool fToValue) override
Element * GetLast()
Definition: C4Gui.h:830
int32_t GetMarginTop() override
Definition: C4Gui.h:2141
void Close(bool fOK)
bool fOK
Definition: C4Gui.h:2083
void ClearFrameDeco()
Definition: C4Gui.h:2200
WoodenLabel * pTitle
Definition: C4Gui.h:2079
void SetTitle(const char *szToTitle, bool fShowCloseButton=true)
bool IsVisible()
Definition: C4Gui.cpp:201
C4Rect rcBounds
Definition: C4Gui.h:385
Element * GetNext() const
Definition: C4Gui.h:449
C4Rect GetContainedClientRect()
Definition: C4Gui.h:448
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
Element * pPrev
Definition: C4Gui.h:377
virtual void StartDragging(CMouse &rMouse, int32_t iX, int32_t iY, DWORD dwKeyParam)
Definition: C4Gui.cpp:259
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:409
Element * pNext
Definition: C4Gui.h:377
void ClientPos2ScreenPos(int32_t &riX, int32_t &riY)
Definition: C4Gui.cpp:231
C4Rect & GetBounds()
Definition: C4Gui.h:445
virtual void UpdateOwnPos()
Definition: C4Gui.h:434
static void DrawToolTip(const char *szTip, C4TargetFacet &cgo, float guix, float guiy)
Definition: C4Gui.cpp:1009
void ShowDialog(Dialog *pDlg, bool fFade)
Definition: C4Gui.cpp:611
CMouse Mouse
Definition: C4Gui.h:2590
void RemoveElement(Element *pChild) override
Definition: C4Gui.cpp:556
void SetClientHeight(int32_t iToHgt)
Definition: C4Gui.h:973
bool IsFrozen() const
Definition: C4Gui.h:971
bool IsScrollBarEnabled()
Definition: C4Gui.h:990
void UnFreeze()
Definition: C4Gui.h:970
void SetScrollBarEnabled(bool fToVal, bool noAutomaticPositioning=false)
void ScrollRangeInView(int32_t iY, int32_t iHgt)
void SetScroll(int32_t iToScroll)
void SetPos(int32_t iXPos, int32_t iYPos)
Definition: C4Gui.h:860
virtual int32_t GetMarginRight()
Definition: C4Gui.h:875
virtual int32_t GetMarginTop()
Definition: C4Gui.h:873
virtual int32_t GetMarginLeft()
Definition: C4Gui.h:874
virtual int32_t GetMarginBottom()
Definition: C4Gui.h:876
void SetIcon(const C4Facet &rfctIcon)
int32_t iTick35
Definition: C4Game.h:130
Definition: C4Id.h:26
static const C4ID None
Definition: C4Id.h:39
bool SkipTags(const char **ppText)
Definition: C4Markup.cpp:123
Definition: C4Menu.h:123
C4Menu()
Definition: C4Menu.cpp:237
bool KeyControl(BYTE byCom)
Definition: C4Menu.cpp:473
int32_t Extra
Definition: C4Menu.h:140
char Caption[C4MaxTitle+1]
Definition: C4Menu.h:147
void UpdateScrollBar()
Definition: C4Menu.cpp:766
void InitSize()
Definition: C4Menu.cpp:739
bool HasPortrait()
Definition: C4Menu.h:242
bool MoveSelection(int32_t iBy, bool fAdjustPosition, bool fDoCalls)
Definition: C4Menu.cpp:522
virtual void Default()
Definition: C4Menu.cpp:246
int32_t ItemCount
Definition: C4Menu.h:138
void UpdateElementPositions()
Definition: C4Menu.cpp:1003
void DrawFrame(C4Surface *sfcSurface, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
Definition: C4Menu.cpp:852
void Clear()
Definition: C4Menu.cpp:271
bool Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand, int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=nullptr, const char *szInfoCaption=nullptr, C4ID idID=C4ID::None, const char *szCommand2=nullptr, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true)
Definition: C4Menu.cpp:350
int32_t GetMarginLeft() override
Definition: C4Menu.h:259
int32_t VisibleCount
Definition: C4Menu.h:145
int32_t ExtraData
Definition: C4Menu.h:140
int32_t GetMarginRight() override
Definition: C4Menu.h:260
bool AddRefSym(const char *szCaption, const C4Facet &fctSymbol, const char *szCommand, int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=nullptr, const char *szInfoCaption=nullptr, C4ID idID=C4ID::None, const char *szCommand2=nullptr, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true)
Definition: C4Menu.cpp:337
bool fActive
Definition: C4Menu.h:153
C4MenuItem * GetItem(int32_t iIndex)
Definition: C4Menu.cpp:512
void SetPermanent(bool fPermanent)
Definition: C4Menu.cpp:862
virtual void OnSelectionChanged(int32_t iNewSelection)
Definition: C4Menu.h:232
bool TryClose(bool fOK, bool fControl)
Definition: C4Menu.cpp:280
void UserClose(bool fOK) override
Definition: C4Menu.cpp:1136
int32_t GetItemCount()
Definition: C4Menu.cpp:517
bool SetTextProgress(int32_t iToProgress, bool fAdd)
Definition: C4Menu.cpp:958
virtual void OnUserSelectItem(int32_t Player, int32_t iIndex)
Definition: C4Menu.h:234
int32_t GetIdentification()
Definition: C4Menu.cpp:612
void InitLocation(C4Facet &cgo)
Definition: C4Menu.cpp:624
bool SetLocation(int32_t iX, int32_t iY)
Definition: C4Menu.cpp:951
void SetEqualItemHeight(bool fToVal)
Definition: C4Menu.h:198
void UserEnter(int32_t Player, C4MenuItem *pItem, bool fRight)
Definition: C4Menu.cpp:1126
void ClearPointers(C4Object *pObj)
Definition: C4Menu.cpp:1158
bool Enter(bool fRight=false)
Definition: C4Menu.cpp:485
virtual void OnUserEnter(int32_t Player, int32_t iIndex, bool fRight)
Definition: C4Menu.h:235
StdStrBuf CloseCommand
Definition: C4Menu.h:146
virtual void OnUserClose()
Definition: C4Menu.h:236
virtual bool DoRefillInternal(bool &rfRefilled)
Definition: C4Menu.h:230
void SetAlignment(int32_t iAlignment)
Definition: C4Menu.cpp:857
friend class C4MenuItem
Definition: C4Menu.h:263
int32_t Lines
Definition: C4Menu.h:143
void AdjustPosition()
Definition: C4Menu.cpp:588
bool Control(BYTE byCom, int32_t iData)
Definition: C4Menu.cpp:420
int32_t Style
Definition: C4Menu.h:136
C4FacetSurface Symbol
Definition: C4Menu.h:148
virtual bool MenuCommand(const char *szCommand, bool fIsCloseCommand)
Definition: C4Menu.h:231
bool HasMouse()
Definition: C4Menu.cpp:1149
int32_t TimeOnSelection
Definition: C4Menu.h:137
bool fHasPortrait
Definition: C4Menu.h:150
virtual bool IsReadOnly()
Definition: C4Menu.h:237
void UserSelectItem(int32_t Player, C4MenuItem *pItem)
Definition: C4Menu.cpp:1116
int32_t ItemWidth
Definition: C4Menu.h:139
bool fEqualIconItemHeight
Definition: C4Menu.h:152
void DrawElement(C4TargetFacet &cgo) override
Definition: C4Menu.cpp:808
C4GUI::ScrollWindow * pClientWindow
Definition: C4Menu.h:149
int32_t ItemHeight
Definition: C4Menu.h:139
bool DoInit(C4FacetSurface &fctSymbol, const char *szEmpty, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal)
Definition: C4Menu.cpp:300
int32_t Alignment
Definition: C4Menu.h:144
C4MenuItem * GetSelectedItem()
Definition: C4Menu.cpp:583
void Draw(C4TargetFacet &cgo) override
Definition: C4Menu.cpp:775
bool Refill()
Definition: C4Menu.cpp:915
void ClearItems()
Definition: C4Menu.cpp:895
void SetCloseCommand(const char *strCommand)
Definition: C4Menu.cpp:1144
bool NeedRefill
Definition: C4Menu.h:135
void UpdateOwnPos() override
Definition: C4Menu.cpp:1108
C4Viewport * GetViewport() override
Definition: C4Menu.cpp:993
int32_t GetMarginBottom() override
Definition: C4Menu.h:258
void Execute()
Definition: C4Menu.cpp:903
bool SetPosition(int32_t iPosition)
Definition: C4Menu.cpp:604
bool LocationSet
Definition: C4Menu.h:133
int32_t GetSelection()
Definition: C4Menu.cpp:599
virtual int32_t GetControllingPlayer()
Definition: C4Menu.h:238
bool SetSelection(int32_t iSelection, bool fAdjustPosition, bool fDoCalls)
Definition: C4Menu.cpp:544
virtual bool IsCloseDenied()
Definition: C4Menu.h:233
bool Permanent
Definition: C4Menu.h:134
bool IsActive()
Definition: C4Menu.cpp:480
int32_t Identification
Definition: C4Menu.h:141
void AdjustSelection()
Definition: C4Menu.cpp:925
bool DoInitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal)
Definition: C4Menu.cpp:307
int32_t Columns
Definition: C4Menu.h:142
bool IsContextMenu()
Definition: C4Menu.h:164
void SetSize(int32_t iToWdt, int32_t iToHgt)
Definition: C4Menu.cpp:617
int32_t Selection
Definition: C4Menu.h:137
bool fTextProgressing
Definition: C4Menu.h:151
bool RefillInternal()
Definition: C4Menu.cpp:867
void DoTextProgress(int32_t &riByVal)
Definition: C4Menu.cpp:71
class C4Menu * pMenu
Definition: C4Menu.h:86
C4ID id
Definition: C4Menu.h:76
C4MenuItem(C4Menu *pMenu, int32_t iIndex, const char *szCaption, const char *szCommand, int32_t iCount, C4Object *pObject, const char *szInfoCaption, C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, int32_t iStyle, bool fIsSelectable)
Definition: C4Menu.cpp:48
bool IsSelectable
Definition: C4Menu.h:88
char InfoCaption[2 *C4MaxTitle+1]
Definition: C4Menu.h:74
int32_t iValue
Definition: C4Menu.h:83
~C4MenuItem() override
Definition: C4Menu.cpp:66
void RefSymbol(const C4Facet &fctSymbol)
Definition: C4Menu.h:105
uint32_t dwSymbolClr
Definition: C4Menu.h:81
void DrawElement(C4TargetFacet &cgo) override
Definition: C4Menu.cpp:122
char Caption[C4MaxTitle+1]
Definition: C4Menu.h:71
C4FacetSurface Symbol
Definition: C4Menu.h:78
C4DefGraphics * pSymbolGraphics
Definition: C4Menu.h:80
void SetGraphics(C4Object *pObj)
Definition: C4Menu.h:103
void MouseInput(class C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) override
Definition: C4Menu.cpp:200
char Command[_MAX_FNAME_LEN+30]
Definition: C4Menu.h:72
void GrabSymbol(C4FacetSurface &fctSymbol)
Definition: C4Menu.h:102
bool fSelected
Definition: C4Menu.h:84
void ClearPointers(C4Object *pObj)
Definition: C4Menu.h:115
int32_t iStyle
Definition: C4Menu.h:85
bool fOwnValue
Definition: C4Menu.h:82
char Command2[_MAX_FNAME_LEN+30]
Definition: C4Menu.h:73
void MouseEnter(class C4GUI::CMouse &rMouse) override
Definition: C4Menu.cpp:226
void SetSelected(bool fToVal)
Definition: C4Menu.h:106
C4Object * pSymbolObj
Definition: C4Menu.h:79
int32_t TextDisplayProgress
Definition: C4Menu.h:89
int32_t Count
Definition: C4Menu.h:75
int32_t iIndex
Definition: C4Menu.h:87
int32_t GetPlayer()
void DrawPicture(C4Facet &cgo, bool fSelected=false, C4DrawTransform *transform=nullptr)
int32_t MouseControl
Definition: C4Player.h:92
C4Player * Get(int iPlayer) const
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
float TargetY
Definition: C4Facet.h:165
float TargetX
Definition: C4Facet.h:165
C4Viewport * GetNext()
Definition: C4Viewport.h:69
C4Viewport * GetFirstViewport()
Definition: C4Viewport.h:159
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)
const char * getData() const
Definition: StdBuf.h:442
void Copy()
Definition: StdBuf.h:467
const char * getPtr(size_t i) const
Definition: StdBuf.h:448
void Clear()
Definition: StdBuf.h:466
size_t getLength() const
Definition: StdBuf.h:445