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