TOOLTIP.CPP 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // ToolTip.cpp
  19. #include "function.h"
  20. #include "ToolTip.h"
  21. #include "IconList.h"
  22. //#include "WolDebug.h"
  23. bool SaveSurfaceRect( int xRect, int yRect, int wRect, int hRect, char* pBits, WindowNumberType window );
  24. bool RestoreSurfaceRect( int xRect, int yRect, int wRect, int hRect, const char* pBits, WindowNumberType window );
  25. //***********************************************************************************************
  26. ToolTipClass::ToolTipClass( GadgetClass* pGadget, const char* szText, int xShow, int yShow,
  27. bool bRightAlign /* = false */, bool bIconList /*= false */ )
  28. : pGadget( pGadget ), xShow( xShow ), yShow( yShow ), next( NULL ), bShowing( false ), bIconList( bIconList ),
  29. bRightAlign( bRightAlign )
  30. {
  31. if( szText )
  32. {
  33. if( strlen( szText ) > TOOLTIPTEXT_MAX_LEN )
  34. strcpy( szTip, "Tooltip too long!" );
  35. else
  36. strcpy( szTip, szText );
  37. }
  38. else
  39. *szTip = 0;
  40. Set_Font( TypeFontPtr );
  41. Fancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TYPE ); // Required before String_Pixel_Width() call, for god's sake.
  42. wShow = String_Pixel_Width( szTip ) + 2;
  43. hShow = 11;
  44. if( !bIconList )
  45. {
  46. pSaveRect = new char[ wShow * hShow ]; // Else it is reallocated on every draw.
  47. if( bRightAlign )
  48. this->xShow -= wShow;
  49. }
  50. else
  51. pSaveRect = NULL;
  52. // bIconList is true if tooltips appear for individual line items in an iconlist.
  53. // szText in this case is ignored.
  54. // yShow is the y position of the top row's tooltip - other rows will be offset from here.
  55. }
  56. //***********************************************************************************************
  57. ToolTipClass* ToolTipClass::GetToolTipHit()
  58. {
  59. // Returns 'this' if the mouse is over gadget bound to tooltip.
  60. // Otherwise calls the same function in the next tooltip in the list of which *this is a part.
  61. if( bGadgetHit() )
  62. return this;
  63. else if( next )
  64. return next->GetToolTipHit();
  65. else
  66. return NULL;
  67. }
  68. //***********************************************************************************************
  69. bool ToolTipClass::bGadgetHit() const
  70. {
  71. // Returns true if the mouse is currently over the gadget to which *this is bound.
  72. int x = Get_Mouse_X();
  73. int y = Get_Mouse_Y();
  74. return ( x > pGadget->X && x < pGadget->X + pGadget->Width && y > pGadget->Y && y < pGadget->Y + pGadget->Height );
  75. }
  76. //***********************************************************************************************
  77. void ToolTipClass::Move( int xShow, int yShow )
  78. {
  79. bool bRestoreShow = false;
  80. if( bShowing )
  81. {
  82. bRestoreShow = true;
  83. Unshow();
  84. }
  85. this->xShow = xShow;
  86. if( !bIconList )
  87. {
  88. if( bRightAlign )
  89. this->xShow -= wShow;
  90. }
  91. this->yShow = yShow;
  92. if( bRestoreShow )
  93. Show();
  94. }
  95. //***********************************************************************************************
  96. void ToolTipClass::Show()
  97. {
  98. if( !bShowing )
  99. {
  100. Set_Font( TypeFontPtr );
  101. int xShowUse = xShow, yShowUse, wShowUse;
  102. const char* szTipUse;
  103. if( !bIconList )
  104. {
  105. yShowUse = yShow;
  106. wShowUse = wShow;
  107. szTipUse = szTip;
  108. }
  109. else
  110. {
  111. IconListClass* pIconList = (IconListClass*)pGadget;
  112. iLastIconListIndex = pIconList->IndexUnderMouse();
  113. if( iLastIconListIndex < 0 )
  114. {
  115. // Nothing to show.
  116. bShowing = true;
  117. return;
  118. }
  119. yShowUse = pIconList->OffsetToIndex( iLastIconListIndex, yShow );
  120. szTipUse = pIconList->Get_Item_Help( iLastIconListIndex );
  121. if( !szTipUse || *szTipUse == 0 )
  122. {
  123. // Nothing to show.
  124. bShowing = true;
  125. bLastShowNoText = true;
  126. return;
  127. }
  128. Fancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TYPE ); // Required before String_Pixel_Width() call, for god's sake.
  129. wShowUse = String_Pixel_Width( szTipUse ) + 2;
  130. if( bRightAlign )
  131. xShowUse -= wShowUse;
  132. delete [] pSaveRect;
  133. pSaveRect = new char[ wShowUse * hShow ];
  134. bLastShowNoText = false;
  135. xLastShow = xShowUse;
  136. yLastShow = yShowUse;
  137. wLastShow = wShowUse;
  138. }
  139. // Save rect about to be corrupted.
  140. Hide_Mouse();
  141. SaveSurfaceRect( xShowUse, yShowUse, wShowUse, hShow, pSaveRect, WINDOW_MAIN );
  142. // Draw text.
  143. //Simple_Text_Print( szTipUse, xShowUse, yShowUse, GadgetClass::Get_Color_Scheme(), ColorRemaps[ PCOLOR_BROWN ].Color, TPF_TYPE ); //TPF_DROPSHADOW );
  144. Simple_Text_Print( szTipUse, xShowUse, yShowUse, GadgetClass::Get_Color_Scheme(), BLACK, TPF_TYPE ); //TPF_DROPSHADOW );
  145. // Draw bounding rect.
  146. // LogicPage->Draw_Rect( xShowUse, yShowUse, xShowUse + wShowUse - 1, yShowUse + hShow - 1, ColorRemaps[ PCOLOR_GOLD ].Color );
  147. Draw_Box( xShowUse, yShowUse, wShowUse, hShow, BOXSTYLE_BOX, false );
  148. Show_Mouse();
  149. bShowing = true;
  150. }
  151. }
  152. //***********************************************************************************************
  153. void ToolTipClass::Unshow()
  154. {
  155. if( bShowing )
  156. {
  157. int xShowUse, yShowUse, wShowUse;
  158. if( !bIconList )
  159. {
  160. xShowUse = xShow;
  161. wShowUse = wShow;
  162. yShowUse = yShow;
  163. }
  164. else
  165. {
  166. if( iLastIconListIndex == -1 || bLastShowNoText )
  167. {
  168. // Nothing to restore.
  169. bShowing = false;
  170. return;
  171. }
  172. // (Can't rely on iconlist being the same as when Show() occurred.)
  173. // IconListClass* pIconList = (IconListClass*)pGadget;
  174. // yShowUse = pIconList->OffsetToIndex( iLastIconListIndex, yShow );
  175. // const char* szTipUsed = pIconList->Get_Item_Help( iLastIconListIndex );
  176. // if( !szTipUsed || *szTipUsed == 0 )
  177. // {
  178. // // Nothing to restore.
  179. // bShowing = false;
  180. // return;
  181. // }
  182. // Fancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TYPE ); // Required before String_Pixel_Width() call, for god's sake.
  183. // wShowUse = String_Pixel_Width( szTipUsed ) + 2;
  184. // if( bRightAlign )
  185. // xShowUse -= wShowUse;
  186. xShowUse = xLastShow;
  187. yShowUse = yLastShow;
  188. wShowUse = wLastShow;
  189. }
  190. Hide_Mouse();
  191. RestoreSurfaceRect( xShowUse, yShowUse, wShowUse, hShow, pSaveRect, WINDOW_MAIN );
  192. Show_Mouse();
  193. bShowing = false;
  194. }
  195. }
  196. //***********************************************************************************************
  197. bool ToolTipClass::bOverDifferentLine() const
  198. {
  199. // bIconList must be true if this is being used.
  200. // Returns true if the iconlist line that the mouse is over is different than the last time Show() was called.
  201. return ( ((IconListClass*)pGadget)->IndexUnderMouse() != iLastIconListIndex );
  202. }
  203. //***********************************************************************************************
  204. bool SaveSurfaceRect( int xRect, int yRect, int wRect, int hRect, char* pBits, WindowNumberType window )
  205. {
  206. // Saves a rect of the LogicPage DirectDraw surface to pBits.
  207. // if( wRect * hRect > iBufferSize )
  208. // {
  209. // debugprint( "SaveSurfaceRect failed.\n" );
  210. // return false;
  211. // }
  212. GraphicViewPortClass draw_window( LogicPage->Get_Graphic_Buffer(),
  213. WindowList[window][WINDOWX] + LogicPage->Get_XPos(),
  214. WindowList[window][WINDOWY] + LogicPage->Get_YPos(),
  215. WindowList[window][WINDOWWIDTH],
  216. WindowList[window][WINDOWHEIGHT] );
  217. if( draw_window.Lock() )
  218. {
  219. int iPitchSurf = draw_window.Get_Pitch() + draw_window.Get_Width(); // Meaning of "Pitch" in this class seems to mean the eol skip.
  220. const char* pLineSurf = (char*)draw_window.Get_Offset() + xRect + yRect * iPitchSurf;
  221. char* pLineSave = pBits;
  222. // ajw - Should copy DWORDs here instead for speed.
  223. for( int y = 0; y != hRect; y++ )
  224. {
  225. const char* pSurf = pLineSurf;
  226. char* pSave = pLineSave;
  227. for( int x = 0; x != wRect; x++ )
  228. *pSave++ = *pSurf++;
  229. pLineSurf += iPitchSurf;
  230. pLineSave += wRect;
  231. }
  232. draw_window.Unlock();
  233. return true;
  234. }
  235. else
  236. {
  237. // debugprint( "SaveSurfaceRect Could not lock surface.\n" );
  238. return false;
  239. }
  240. }
  241. //***********************************************************************************************
  242. bool RestoreSurfaceRect( int xRect, int yRect, int wRect, int hRect, const char* pBits, WindowNumberType window )
  243. {
  244. // Copies a saved rect of bits back to the LogicPage DD surface.
  245. GraphicViewPortClass draw_window( LogicPage->Get_Graphic_Buffer(),
  246. WindowList[window][WINDOWX] + LogicPage->Get_XPos(),
  247. WindowList[window][WINDOWY] + LogicPage->Get_YPos(),
  248. WindowList[window][WINDOWWIDTH],
  249. WindowList[window][WINDOWHEIGHT] );
  250. if( draw_window.Lock() )
  251. {
  252. int iPitchSurf = draw_window.Get_Pitch() + draw_window.Get_Width(); // Meaning of "Pitch" in this class seems to mean the eol skip.
  253. char* pLineSurf = (char*)draw_window.Get_Offset() + xRect + yRect * iPitchSurf;
  254. const char* pLineSave = pBits;
  255. // ajw - Should copy DWORDs here instead for speed.
  256. for( int y = 0; y != hRect; y++ )
  257. {
  258. char* pSurf = pLineSurf;
  259. const char* pSave = pLineSave;
  260. for( int x = 0; x != wRect; x++ )
  261. *pSurf++ = *pSave++;
  262. pLineSurf += iPitchSurf;
  263. pLineSave += wRect;
  264. }
  265. draw_window.Unlock();
  266. return true;
  267. }
  268. else
  269. {
  270. // debugprint( "RestoreSurfaceRect Could not lock surface.\n" );
  271. return false;
  272. }
  273. }