1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2009-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 // generic user interface 17 // eye candy 18 19 #include "C4Include.h" 20 #include "gui/C4Gui.h" 21 22 #include "graphics/C4Draw.h" 23 #include "graphics/C4GraphicsResource.h" 24 #include "gui/C4MouseControl.h" 25 26 namespace C4GUI 27 { 28 29 // -------------------------------------------------- 30 // Label 31 DrawElement(C4TargetFacet & cgo)32 void Label::DrawElement(C4TargetFacet &cgo) 33 { 34 // print out 35 pDraw->TextOut(sText.getData(), *pFont, 1.0f, cgo.Surface, x0 + cgo.TargetX, rcBounds.y + cgo.TargetY, dwFgClr, iAlign, fMarkup); 36 } 37 Label(const char * szLblText,int32_t iX0,int32_t iTop,int32_t iAlign,DWORD dwFClr,CStdFont * pFont,bool fMakeReadableOnBlack,bool fMarkup)38 Label::Label(const char *szLblText, int32_t iX0, int32_t iTop, int32_t iAlign, DWORD dwFClr, CStdFont *pFont, bool fMakeReadableOnBlack, bool fMarkup) 39 : Element(), dwFgClr(dwFClr), x0(iX0), iAlign(iAlign), pFont(pFont), cHotkey(0), fAutosize(true), fMarkup(fMarkup), pClickFocusControl(nullptr) 40 { 41 // make color readable 42 if (fMakeReadableOnBlack) MakeColorReadableOnBlack(dwFgClr); 43 // default font 44 if (!this->pFont) this->pFont = &::GraphicsResource.TextFont; 45 // set top 46 rcBounds.y = iTop; 47 // update text 48 SetText(szLblText); 49 } 50 Label(const char * szLblText,const C4Rect & rcBounds,int32_t iAlign,DWORD dwFClr,CStdFont * pFont,bool fMakeReadableOnBlack,bool fAutosize,bool fMarkup)51 Label::Label(const char *szLblText, const C4Rect &rcBounds, int32_t iAlign, DWORD dwFClr, CStdFont *pFont, bool fMakeReadableOnBlack, bool fAutosize, bool fMarkup) 52 : Element(), dwFgClr(dwFClr), iAlign(iAlign), pFont(pFont), cHotkey(0), fAutosize(fAutosize), fMarkup(fMarkup), pClickFocusControl(nullptr) 53 { 54 // make color readable 55 if (fMakeReadableOnBlack) MakeColorReadableOnBlack(dwFgClr); 56 this->rcBounds = rcBounds; 57 // default font 58 if (!this->pFont) this->pFont = &::GraphicsResource.TextFont; 59 // set x0 60 UpdateOwnPos(); 61 // update text 62 SetText(szLblText); 63 } 64 MouseInput(CMouse & rMouse,int32_t iButton,int32_t iX,int32_t iY,DWORD dwKeyParam)65 void Label::MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) 66 { 67 // left-click changes focus 68 if (pClickFocusControl && iButton == C4MC_Button_LeftDown) 69 GetDlg()->SetFocus(pClickFocusControl, true); 70 // inherited 71 Element::MouseInput(rMouse, iButton, iX, iY, dwKeyParam); 72 } 73 SetText(const char * szToText,bool fAllowHotkey)74 void Label::SetText(const char *szToText, bool fAllowHotkey) 75 { 76 // set new text 77 if (szToText) 78 { 79 sText.Copy(szToText); 80 // expand hotkey markup 81 if (fAllowHotkey && fMarkup) ExpandHotkeyMarkup(sText, cHotkey); 82 } 83 else 84 { 85 sText=""; 86 cHotkey=0; 87 } 88 // update according to text only if autosize label (not wooden) 89 if (!fAutosize) return; 90 // get text extents 91 pFont->GetTextExtent(sText.getData(), rcBounds.Wdt, rcBounds.Hgt, fMarkup); 92 // update pos 93 SetX0(x0); 94 } 95 UpdateOwnPos()96 void Label::UpdateOwnPos() 97 { 98 // update text drawing pos 99 switch (iAlign) 100 { 101 case ALeft: x0 = rcBounds.x + GetLeftIndent(); break; 102 case ACenter: x0 = rcBounds.x+rcBounds.Wdt/2; break; 103 case ARight: x0 = rcBounds.x+rcBounds.Wdt; break; 104 } 105 } 106 OnHotkey(uint32_t cHotkey)107 bool Label::OnHotkey(uint32_t cHotkey) 108 { 109 // if hotkey matches and focus control is assigned, set focus 110 if (this->cHotkey == cHotkey && pClickFocusControl) 111 { 112 GetDlg()->SetFocus(pClickFocusControl, false); 113 return true; 114 } 115 else return false; 116 } 117 SetX0(int32_t iToX0)118 void Label::SetX0(int32_t iToX0) 119 { 120 x0 = iToX0; 121 // update x-startpos 122 switch (iAlign) 123 { 124 case ALeft: rcBounds.x = x0; break; 125 case ACenter: rcBounds.x = x0 - rcBounds.Wdt/2; break; 126 case ARight: rcBounds.x = x0 - rcBounds.Wdt; break; 127 } 128 // size might have changed 129 UpdateSize(); 130 } 131 132 133 // -------------------------------------------------- 134 // WoodenLabel 135 DrawElement(C4TargetFacet & cgo)136 void WoodenLabel::DrawElement(C4TargetFacet &cgo) 137 { 138 // draw wood 139 DrawBar(cgo, ::GraphicsResource.barCaption); 140 // draw symbol 141 if (fctIcon.Surface) 142 { 143 C4Facet cgoSymbol(cgo.Surface, cgo.TargetX + rcBounds.x + 1, cgo.TargetY + rcBounds.y + 1, rcBounds.Hgt-2, rcBounds.Hgt-2); 144 fctIcon.Draw(cgoSymbol); 145 } 146 // calculations for automatic scrolling 147 int32_t iXOff = 0; 148 if (iAlign == ALeft) iXOff += 5; 149 if (iAutoScrollDelay) 150 { 151 C4TimeMilliseconds tNow = C4TimeMilliseconds::Now(); 152 if (tNow >= tLastChangeTime + iAutoScrollDelay) 153 { 154 if (!iScrollDir) iScrollDir=1; 155 int32_t iMaxScroll = std::max<int32_t>(pFont->GetTextWidth(sText.getData(), true) + (x0 - rcBounds.x) + iXOff + GetRightIndent() - rcBounds.Wdt, 0); 156 if (iMaxScroll) 157 { 158 iScrollPos += iScrollDir; 159 if (iScrollPos >= iMaxScroll || iScrollPos < 0) 160 { 161 iScrollDir = -iScrollDir; 162 iScrollPos += iScrollDir; 163 tLastChangeTime = tNow; 164 } 165 } 166 } 167 iXOff -= iScrollPos; 168 } 169 // print out text; clipped 170 pDraw->StorePrimaryClipper(); 171 pDraw->SetPrimaryClipper(rcBounds.x + GetLeftIndent() + cgo.TargetX, rcBounds.y + cgo.TargetY, rcBounds.x+rcBounds.Wdt - GetRightIndent() + cgo.TargetX, rcBounds.y+rcBounds.Hgt + cgo.TargetY); 172 pDraw->TextOut(sText.getData(), *pFont, 1.0f, cgo.Surface, x0 + cgo.TargetX + iXOff, rcBounds.y + cgo.TargetY + (rcBounds.Hgt-pFont->GetLineHeight())/2-1, dwFgClr, iAlign); 173 pDraw->RestorePrimaryClipper(); 174 } 175 GetDefaultHeight(CStdFont * pUseFont)176 int32_t WoodenLabel::GetDefaultHeight(CStdFont *pUseFont) 177 { 178 if (!pUseFont) pUseFont = &(::GraphicsResource.TextFont); 179 return std::max<int32_t>(pUseFont->GetLineHeight(), C4GUI_MinWoodBarHgt); 180 } 181 SetIcon(const C4Facet & rfctIcon)182 void WoodenLabel::SetIcon(const C4Facet &rfctIcon) 183 { 184 // set icon 185 fctIcon = rfctIcon; 186 // realign text to left for set icons 187 if (fctIcon.Surface) 188 iAlign = ALeft; 189 else 190 iAlign = ACenter; 191 UpdateOwnPos(); 192 } 193 ResetAutoScroll()194 void WoodenLabel::ResetAutoScroll() 195 { 196 iScrollPos = iScrollDir = 0; 197 } 198 199 // -------------------------------------------------- 200 // MultilineLabel 201 MultilineLabel(const C4Rect & rcBounds,int32_t iMaxLines,int32_t iMaxBuf,const char * szIndentChars,bool fAutoGrow,bool fMarkup)202 MultilineLabel::MultilineLabel(const C4Rect &rcBounds, int32_t iMaxLines, int32_t iMaxBuf, const char *szIndentChars, bool fAutoGrow, bool fMarkup) // ctor 203 : Element(), Lines(iMaxBuf, iMaxLines, rcBounds.Wdt, szIndentChars, fAutoGrow, fMarkup), fMarkup(fMarkup) 204 { 205 // set bounds 206 this->rcBounds = rcBounds; 207 // update height (min height) 208 UpdateOwnPos(); 209 } 210 DrawElement(C4TargetFacet & cgo)211 void MultilineLabel::DrawElement(C4TargetFacet &cgo) 212 { 213 // get clipping 214 int iClipX, iClipY, iClipX2, iClipY2; 215 pDraw->GetPrimaryClipper(iClipX, iClipY, iClipX2, iClipY2); 216 // draw all lines 217 int32_t iIndex = 0; const char *szLine; 218 int32_t iY = rcBounds.y + cgo.TargetY; 219 CStdFont *pLineFont; DWORD dwLineClr; bool fNewParagraph; 220 while ((szLine = Lines.GetLine(iIndex, &pLineFont, &dwLineClr, &fNewParagraph))) 221 { 222 int32_t iFontLineHeight = pLineFont->GetLineHeight(); 223 // indents between paragraphs 224 if (fNewParagraph && iIndex) iY += iFontLineHeight/3; 225 // clip 226 if (iY > iClipY2) break; 227 if (iY >= iClipY-iFontLineHeight) 228 { 229 // draw line 230 pDraw->TextOut(szLine, *pLineFont, 1.0f, cgo.Surface, rcBounds.x + cgo.TargetX, iY, dwLineClr, ALeft, fMarkup); 231 } 232 // advance line 233 iY += iFontLineHeight; 234 ++iIndex; 235 } 236 } 237 UpdateSize()238 void MultilineLabel::UpdateSize() 239 { 240 // forward change to line buffer 241 Lines.SetLBWidth(rcBounds.Wdt); 242 UpdateHeight(); 243 } 244 UpdateHeight()245 void MultilineLabel::UpdateHeight() 246 { 247 // size by line count 248 int32_t iIndex = 0; const char *szLine; int32_t iHgt = 0; 249 CStdFont *pLineFont; bool fNewPar; 250 while ((szLine = Lines.GetLine(iIndex, &pLineFont, nullptr, &fNewPar))) 251 { 252 int32_t iFontLineHeight = pLineFont->GetLineHeight(); 253 // indents between separate messages 254 if (fNewPar && iIndex) iHgt += iFontLineHeight/3; 255 // text line height 256 iHgt += iFontLineHeight; 257 ++iIndex; 258 } 259 rcBounds.Hgt = std::max<int32_t>(iHgt, 5); 260 // update parent container 261 Element::UpdateSize(); 262 } 263 AddLine(const char * szLine,CStdFont * pFont,DWORD dwClr,bool fDoUpdate,bool fMakeReadableOnBlack,CStdFont * pCaptionFont)264 void MultilineLabel::AddLine(const char *szLine, CStdFont *pFont, DWORD dwClr, bool fDoUpdate, bool fMakeReadableOnBlack, CStdFont *pCaptionFont) 265 { 266 // make color readable 267 if (fMakeReadableOnBlack) MakeColorReadableOnBlack(dwClr); 268 // forward to line buffer 269 if (szLine) Lines.AppendLines(szLine, pFont, dwClr, pCaptionFont); 270 // adjust height 271 if (fDoUpdate) UpdateSize(); 272 } 273 Clear(bool fDoUpdate)274 void MultilineLabel::Clear(bool fDoUpdate) 275 { 276 // forward to line buffer 277 Lines.Clear(); 278 // adjust height 279 if (fDoUpdate) UpdateSize(); 280 } 281 282 283 284 // -------------------------------------------------- 285 // HorizontalLine 286 DrawElement(C4TargetFacet & cgo)287 void HorizontalLine::DrawElement(C4TargetFacet &cgo) 288 { 289 // draw horizontal line 290 int32_t iX1 = rcBounds.x + cgo.TargetX, iX2 = iX1 + rcBounds.Wdt, 291 iY = rcBounds.y + cgo.TargetY; 292 pDraw->DrawLineDw(cgo.Surface, (float)(iX1+1), (float)(iY+1), (float)(iX2-1), (float)(iY+1), dwShadowClr); 293 pDraw->DrawLineDw(cgo.Surface, (float)iX1, (float)iY, (float)(iX2-2), (float)iY, dwClr); 294 } 295 296 297 // -------------------------------------------------- 298 // ProgressBar 299 DrawElement(C4TargetFacet & cgo)300 void ProgressBar::DrawElement(C4TargetFacet &cgo) 301 { 302 // do not draw in negative progress 303 if (iProgress<0) return; 304 CStdFont &rFont = ::GraphicsResource.TextFont; 305 // draw border 306 Draw3DFrame(cgo); 307 // calc progress width 308 int32_t iProgressWdt = (rcBounds.Wdt-4) * iProgress / iMax; 309 // draw progress 310 ::GraphicsResource.fctProgressBar.DrawX(cgo.Surface, cgo.TargetX+rcBounds.x+2, cgo.TargetY+rcBounds.y+2, iProgressWdt, rcBounds.Hgt-2); 311 // print out progress text 312 char szPrg[32+1]; 313 sprintf(szPrg, "%i%%", 100 * iProgress / iMax); 314 pDraw->TextOut(szPrg, rFont, 1.0f, cgo.Surface, cgo.TargetX+rcBounds.GetMiddleX(), rcBounds.y + cgo.TargetY + (rcBounds.Hgt-rFont.GetLineHeight())/2-1, C4GUI_ProgressBarFontClr, ACenter); 315 } 316 317 318 // -------------------------------------------------- 319 // Picture 320 Picture(const C4Rect & rcBounds,bool fAspect)321 Picture::Picture(const C4Rect &rcBounds, bool fAspect) : fCustomDrawClr(false), fAnimate(false) 322 { 323 // set values 324 this->fAspect = fAspect; 325 this->rcBounds = rcBounds; 326 // no facet yet 327 } 328 DrawElement(C4TargetFacet & cgo)329 void Picture::DrawElement(C4TargetFacet &cgo) 330 { 331 // animation? 332 C4Facet *pDrawFacet, DrawFacet; 333 if (fAnimate) 334 { 335 if (++iPhaseTime > iDelay) 336 { 337 int32_t iPhasesX=1, iPhasesY=1; 338 Facet.GetPhaseNum(iPhasesX, iPhasesY); 339 if (++iAnimationPhase >= iPhasesX) iAnimationPhase = 0; 340 iPhaseTime = 0; 341 } 342 DrawFacet = Facet.GetPhase(iAnimationPhase); 343 pDrawFacet = &DrawFacet; 344 } 345 else 346 pDrawFacet = &Facet; 347 // draw the facet 348 C4Facet cgo2 = cgo; 349 cgo2.X = rcBounds.x + cgo.TargetX; 350 cgo2.Y = rcBounds.y + cgo.TargetY; 351 cgo2.Wdt = rcBounds.Wdt; 352 cgo2.Hgt = rcBounds.Hgt; 353 if (fCustomDrawClr) 354 { 355 pDrawFacet->DrawClr(cgo2, fAspect, dwDrawClr); 356 } 357 else 358 pDrawFacet->Draw(cgo2, fAspect); 359 } 360 EnsureOwnSurface()361 bool Picture::EnsureOwnSurface() 362 { 363 // no surface? 364 if (!Facet.Surface) return false; 365 // equals face already? 366 if (Facet.Surface == &Facet.GetFace()) return true; 367 // then create as a copy 368 C4Facet cgo = Facet; 369 if (!Facet.Create(cgo.Wdt, cgo.Hgt)) return false; 370 cgo.Draw(Facet); 371 return true; 372 } 373 374 SetAnimated(bool fEnabled,int iDelay)375 void Picture::SetAnimated(bool fEnabled, int iDelay) 376 { 377 if ((fAnimate = fEnabled)) 378 { 379 // starts cycling through all phases of the specified facet 380 iAnimationPhase=iPhaseTime=0; 381 this->iDelay = iDelay; 382 } 383 } 384 385 386 387 // -------------------------------------------------- 388 // OverlayPicture 389 OverlayPicture(const C4Rect & rcBounds,bool fAspect,const C4Facet & rOverlayImage,int iBorderSize)390 OverlayPicture::OverlayPicture(const C4Rect &rcBounds, bool fAspect, const C4Facet &rOverlayImage, int iBorderSize) 391 : Picture(rcBounds, fAspect), iBorderSize(iBorderSize), OverlayImage(rOverlayImage) 392 { 393 } 394 DrawElement(C4TargetFacet & cgo)395 void OverlayPicture::DrawElement(C4TargetFacet &cgo) 396 { 397 // draw inner image 398 C4Facet cgo2 = cgo; 399 cgo2.X = rcBounds.x + cgo.TargetX + iBorderSize * rcBounds.Wdt / std::max<int>(OverlayImage.Wdt, 1); 400 cgo2.Y = rcBounds.y + cgo.TargetY + iBorderSize * rcBounds.Hgt / std::max<int>(OverlayImage.Hgt, 1); 401 cgo2.Wdt = rcBounds.Wdt - 2 * iBorderSize * rcBounds.Wdt / std::max<int>(OverlayImage.Wdt, 1); 402 cgo2.Hgt = rcBounds.Hgt - 2 * iBorderSize * rcBounds.Hgt / std::max<int>(OverlayImage.Hgt, 1); 403 Facet.Draw(cgo2, fAspect); 404 // draw outer image 405 cgo2.X = rcBounds.x + cgo.TargetX; 406 cgo2.Y = rcBounds.y + cgo.TargetY; 407 cgo2.Wdt = rcBounds.Wdt; 408 cgo2.Hgt = rcBounds.Hgt; 409 OverlayImage.Draw(cgo2, fAspect); 410 } 411 412 413 // -------------------------------------------------- 414 // Icon 415 Icon(const C4Rect & rcBounds,Icons icoIconIndex)416 Icon::Icon(const C4Rect &rcBounds, Icons icoIconIndex) 417 : Picture(rcBounds, true) 418 { 419 // set icon facet 420 SetIcon(icoIconIndex); 421 } 422 SetIcon(Icons icoNewIconIndex)423 void Icon::SetIcon(Icons icoNewIconIndex) 424 { 425 // load icon 426 SetFacet(GetIconFacet(icoNewIconIndex)); 427 } 428 GetIconFacet(Icons icoIconIndex)429 C4Facet Icon::GetIconFacet(Icons icoIconIndex) 430 { 431 if (icoIconIndex == Ico_None) return C4Facet(); 432 C4Facet *rFacet; 433 switch (icoIconIndex & ~0xff) 434 { 435 case Ico_Extended: rFacet = &::GraphicsResource.fctIconsEx; break; 436 case Ico_Controller: rFacet = &::GraphicsResource.fctControllerIcons; break; 437 default: rFacet = &::GraphicsResource.fctIcons; 438 } 439 icoIconIndex = Icons(icoIconIndex & 0xff); 440 int32_t iXMax, iYMax; 441 rFacet->GetPhaseNum(iXMax, iYMax); 442 if (!iXMax) iXMax = 6; 443 return rFacet->GetPhase(icoIconIndex % iXMax, icoIconIndex / iXMax); 444 } 445 446 447 // -------------------------------------------------- 448 // PaintBox 449 MouseInput(CMouse & rMouse,int32_t iButton,int32_t iX,int32_t iY,DWORD dwKeyParam)450 void PaintBox::MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) 451 { 452 } 453 DrawElement(C4TargetFacet & cgo)454 void PaintBox::DrawElement(C4TargetFacet &cgo) 455 { 456 // draw it 457 fctPaint.Draw(cgo.Surface, rcBounds.x+cgo.TargetX, rcBounds.y+cgo.TargetY); 458 } 459 PaintBox(C4Rect & rtBounds,int32_t iSfcWdt,int32_t iSfcHgt)460 PaintBox::PaintBox(C4Rect &rtBounds, int32_t iSfcWdt, int32_t iSfcHgt) 461 { 462 // default surface bounds 463 if (iSfcWdt<0) iSfcWdt = rtBounds.Wdt; 464 if (iSfcHgt<0) iSfcHgt = rtBounds.Hgt; 465 // create surface 466 if (iSfcWdt<=0 || iSfcHgt<=0) return; 467 fctPaint.Create(iSfcWdt, iSfcHgt); 468 } 469 470 PaintBox::~PaintBox() = default; 471 472 473 // -------------------------------------------------- 474 // TextWindow 475 TextWindow(C4Rect & rtBounds,size_t iPicWdt,size_t iPicHgt,size_t iPicPadding,size_t iMaxLines,size_t iMaxTextLen,const char * szIndentChars,bool fAutoGrow,const C4Facet * pOverlayPic,int iOverlayBorder,bool fMarkup)476 TextWindow::TextWindow(C4Rect &rtBounds, size_t iPicWdt, size_t iPicHgt, size_t iPicPadding, size_t iMaxLines, size_t iMaxTextLen, const char *szIndentChars, bool fAutoGrow, const C4Facet *pOverlayPic, int iOverlayBorder, bool fMarkup) 477 : Control(rtBounds), pLogBuffer(nullptr), fDrawBackground(true), fDrawFrame(true), iPicPadding(iPicPadding) 478 { 479 // calc client rect 480 UpdateOwnPos(); 481 // create content scroll window 482 pClientWindow = new ScrollWindow(this); 483 pClientWindow->SetBounds(GetContainedClientRect()); 484 // create content multiline label 485 pLogBuffer = new MultilineLabel(pClientWindow->GetContainedClientRect(), iMaxLines, iMaxTextLen, szIndentChars, fAutoGrow, fMarkup); 486 // add to scroll window 487 pClientWindow->AddElement(pLogBuffer); 488 // update scrolling (for empty buffer) 489 pClientWindow->SetClientHeight(1); 490 // create content picture, if desired 491 C4Rect rcContentSize = pClientWindow->GetClientRect(); 492 if (iPicWdt && iPicHgt) 493 { 494 C4Rect rcImage; 495 rcImage.x = std::max<int32_t>(rcContentSize.GetMiddleX() - iPicWdt/2, 0); 496 rcImage.y = 0; 497 rcImage.Wdt = std::min<size_t>(iPicWdt, rcContentSize.Wdt); 498 rcImage.Hgt = iPicHgt * rcImage.Wdt / iPicWdt; 499 rcContentSize.y += rcImage.Hgt + iPicPadding; 500 if (pOverlayPic) 501 pTitlePicture = new OverlayPicture(rcImage, false, *pOverlayPic, iOverlayBorder); 502 else 503 pTitlePicture = new Picture(rcImage, false); 504 pClientWindow->AddElement(pTitlePicture); 505 } 506 else pTitlePicture = nullptr; 507 508 // update size 509 UpdateSize(); 510 } 511 UpdateSize()512 void TextWindow::UpdateSize() 513 { 514 Control::UpdateSize(); 515 pClientWindow->SetBounds(GetContainedClientRect()); 516 // resize log buffer pos to horizontal extents 517 C4Rect rcChildBounds = pLogBuffer->GetBounds(); 518 rcChildBounds.x = 0; 519 rcChildBounds.y = (pTitlePicture && pTitlePicture->IsVisible()) ? pTitlePicture->GetBounds().Hgt + iPicPadding : 0; 520 rcChildBounds.Wdt = pClientWindow->GetClientRect().Wdt; 521 pLogBuffer->SetBounds(rcChildBounds); 522 } 523 DrawElement(C4TargetFacet & cgo)524 void TextWindow::DrawElement(C4TargetFacet &cgo) 525 { 526 // draw background 527 if (fDrawBackground) pDraw->DrawBoxDw(cgo.Surface, cgo.TargetX+rcBounds.x,cgo.TargetY+rcBounds.y,rcBounds.x+rcBounds.Wdt-1+cgo.TargetX,rcBounds.y+rcBounds.Hgt-1+cgo.TargetY,0x7f000000); 528 // draw frame 529 if (fDrawFrame) Draw3DFrame(cgo); 530 } 531 ElementSizeChanged(Element * pOfElement)532 void TextWindow::ElementSizeChanged(Element *pOfElement) 533 { 534 // inherited 535 if (pOfElement->GetParent() == this) 536 Control::ElementSizeChanged(pOfElement); 537 // update size of scroll control 538 if (pClientWindow && pLogBuffer) 539 pClientWindow->SetClientHeight(pLogBuffer->GetBounds().y + pLogBuffer->GetBounds().Hgt); 540 } 541 ElementPosChanged(Element * pOfElement)542 void TextWindow::ElementPosChanged(Element *pOfElement) 543 { 544 // inherited 545 if (pOfElement->GetParent() == this) 546 Control::ElementSizeChanged(pOfElement); 547 // update size of scroll control 548 if (pClientWindow && pLogBuffer) 549 pClientWindow->SetClientHeight(pLogBuffer->GetBounds().y + pLogBuffer->GetBounds().Hgt); 550 } 551 SetPicture(const C4Facet & rNewPic)552 void TextWindow::SetPicture(const C4Facet &rNewPic) 553 { 554 // update picture 555 if (!pTitlePicture) return; 556 pTitlePicture->SetFacet(rNewPic); 557 // reposition multiline label below picture if any is assigned 558 pLogBuffer->GetBounds().y = rNewPic.Surface ? pTitlePicture->GetBounds().Hgt + iPicPadding : 0; 559 pLogBuffer->UpdateOwnPos(); 560 pTitlePicture->SetVisibility(!!rNewPic.Surface); 561 } 562 563 } // end of namespace 564 565