1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2010-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 // checkbox 18 19 #include "C4Include.h" 20 #include "gui/C4Gui.h" 21 22 #include "graphics/C4Draw.h" 23 #include "graphics/C4FacetEx.h" 24 #include "graphics/C4GraphicsResource.h" 25 #include "gui/C4MouseControl.h" 26 27 namespace C4GUI 28 { 29 30 // ---------------------------------------------------- 31 // CheckBox 32 CheckBox(const C4Rect & rtBounds,const char * szCaption,bool fChecked)33 CheckBox::CheckBox(const C4Rect &rtBounds, const char *szCaption, bool fChecked) 34 : Control(rtBounds), fChecked(fChecked), fMouseOn(false), fEnabled(true), pFont(nullptr) 35 , dwEnabledClr(C4GUI_CheckboxFontClr), dwDisabledClr(C4GUI_CheckboxDisabledFontClr), cHotkey(0) 36 { 37 if (szCaption) 38 { 39 sCaption.Copy(szCaption); 40 ExpandHotkeyMarkup(sCaption, cHotkey); 41 } 42 // key callbacks: Check/Uncheck on space and primary joy button 43 C4CustomKey::CodeList Keys; 44 Keys.emplace_back(K_SPACE); 45 if (Config.Controls.GamepadGuiControl) 46 { 47 ControllerKeys::Ok(Keys); 48 } 49 pKeyCheck = new C4KeyBinding(Keys, "GUICheckboxToggle", KEYSCOPE_Gui, 50 new ControlKeyCB<CheckBox>(*this, &CheckBox::KeyCheck), C4CustomKey::PRIO_Ctrl); 51 pCBHandler = nullptr; 52 } 53 ~CheckBox()54 CheckBox::~CheckBox() 55 { 56 delete pKeyCheck; 57 if (pCBHandler) pCBHandler->DeRef(); 58 } 59 UpdateOwnPos()60 void CheckBox::UpdateOwnPos() 61 { 62 } 63 OnHotkey(uint32_t cHotkey)64 bool CheckBox::OnHotkey(uint32_t cHotkey) 65 { 66 if (cHotkey != this->cHotkey) return false; 67 ToggleCheck(true); 68 return true; 69 } 70 ToggleCheck(bool fByUser)71 void CheckBox::ToggleCheck(bool fByUser) 72 { 73 // user can't toggle if disabled 74 if (fByUser && !fEnabled) return; 75 // sound 76 if (fByUser) GUISound("UI::Tick"); 77 // toggle state 78 fChecked = !fChecked; 79 // callback (last call; may destroy element) 80 if (pCBHandler) pCBHandler->DoCall(this); 81 } 82 MouseInput(CMouse & rMouse,int32_t iButton,int32_t iX,int32_t iY,DWORD dwKeyParam)83 void CheckBox::MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) 84 { 85 if (fEnabled) 86 { 87 // set mouse-on flag depending on whether mouse is over box area 88 fMouseOn = Inside<int32_t>(iX, 0, rcBounds.Hgt) && Inside<int32_t>(iY, 0, rcBounds.Hgt); 89 // left-click within checkbox toggles it 90 if (iButton == C4MC_Button_LeftDown && fMouseOn) 91 { 92 ToggleCheck(true); 93 return; 94 } 95 } 96 // not recognized; base call 97 Control::MouseInput(rMouse, iButton, iX, iY, dwKeyParam); 98 } 99 MouseEnter(CMouse & rMouse)100 void CheckBox::MouseEnter(CMouse &rMouse) 101 { 102 Control::MouseEnter(rMouse); 103 } 104 MouseLeave(CMouse & rMouse)105 void CheckBox::MouseLeave(CMouse &rMouse) 106 { 107 fMouseOn = false; 108 Control::MouseLeave(rMouse); 109 } 110 DrawElement(C4TargetFacet & cgo)111 void CheckBox::DrawElement(C4TargetFacet &cgo) 112 { 113 // left side: check facet (squared) 114 int x0 = rcBounds.x + cgo.TargetX; 115 int y0 = rcBounds.y + cgo.TargetY; 116 ::GraphicsResource.fctCheckbox.GetPhase(fChecked + 2*!fEnabled).DrawX(cgo.Surface, x0, y0, rcBounds.Hgt, rcBounds.Hgt); 117 // right of it: checkbox text 118 CStdFont *pUseFont = pFont ? pFont : &(::GraphicsResource.TextFont); 119 int32_t yOff; float fZoom; 120 if (pUseFont->GetLineHeight() <= rcBounds.Hgt) 121 { 122 yOff = std::max<int32_t>(rcBounds.Hgt - pUseFont->GetLineHeight(), 0)/2; 123 fZoom = 1.0f; 124 } 125 else 126 { 127 yOff = 0; 128 fZoom = (float) rcBounds.Hgt / std::max(pUseFont->GetLineHeight(), 1); 129 } 130 pDraw->TextOut(sCaption.getData(), *pUseFont, fZoom, cgo.Surface, x0 + rcBounds.Hgt + C4GUI_CheckBoxLabelSpacing, y0 + yOff, fEnabled ? dwEnabledClr : dwDisabledClr, ALeft, true); 131 // selection marker 132 if ((fMouseOn && IsInActiveDlg(false)) || HasDrawFocus()) 133 { 134 pDraw->SetBlitMode(C4GFXBLIT_ADDITIVE); 135 ::GraphicsResource.fctButtonHighlightRound.DrawX(cgo.Surface, x0+rcBounds.Hgt*1/4, y0+rcBounds.Hgt*1/4, rcBounds.Hgt*1/2, rcBounds.Hgt*1/2); 136 pDraw->ResetBlitMode(); 137 } 138 } 139 SetOnChecked(BaseCallbackHandler * pCB)140 void CheckBox::SetOnChecked(BaseCallbackHandler *pCB) 141 { 142 if (pCBHandler) pCBHandler->DeRef(); 143 if ((pCBHandler = pCB)) pCB->Ref(); 144 } 145 GetStandardCheckBoxSize(int * piWdt,int * piHgt,const char * szForCaptionText,CStdFont * pUseFont)146 bool CheckBox::GetStandardCheckBoxSize(int *piWdt, int *piHgt, const char *szForCaptionText, CStdFont *pUseFont) 147 { 148 // get needed text size 149 if (!pUseFont) pUseFont = &(::GraphicsResource.TextFont); 150 int32_t iWdt=100, iHgt=32; 151 pUseFont->GetTextExtent(szForCaptionText, iWdt, iHgt, true); 152 // check box height equals text height 153 // add check box plus indent 154 if (piWdt) *piWdt = iWdt + iHgt + C4GUI_CheckBoxLabelSpacing; 155 if (piHgt) *piHgt = iHgt; 156 return true; 157 } 158 159 } // namespace C4GUI 160