#include "stdafx.h" #include "KUIDefine.h" #include "KUIWndManager.h" #include "KResourceManager.h" #include "KUITextureManager.h" #include "KUIControlButton.h" #include "KUIControlStatic.h" #include "KUIControlCombo.h" namespace { KUIWnd* Creator() { return new KUIControlCombo; } bool bRegister = KUIFactory::GetInstance()->RegisterCreator( Creator, "combo_box"); LPCSTR COMBO_BTN_ANI_NAME = "button_common_down"; LPCSTR COMBO_BTN_ID = "_combo_btn_id"; LPCSTR COMBO_FRAME_ANI_NAME = "static_common_background00"; LPCSTR COMBO_UNFOLD_FRAME_ANI_NAME = "static_common_background00"; LPCSTR COMBO_UNFOLD_FRAME_ID = "_combo_unfold_frame_id"; LPCSTR COMBO_UNFOLD_SELECT_ANI_NAME = "static_combo_select"; LPCSTR COMBO_UNFOLD_SELECT_ID = "_combo_unfold_select_id"; const int COMBO_UNFOLD_Y_OFFSET = 0; const int COMBO_BTN_Y_OFFSET = 1; const int COMBO_TEXT_HEIGHT = 12; const int COMBO_TEXT_GAP = 3; const int COMBO_ITEM_HEIGHT = 20; const int COMBO_PHRASE_Y_OFFSET = COMBO_UNFOLD_Y_OFFSET + 3; const int COMBO_MAX_VIEW_LINE = 20; const int COMBO_LEFT_FRAME_WIDTH = 4; const int COMBO_UNFOLD_Y_ADD_HEIGHT = 6; const int COMBO_UNFOLD_SELECT_Y_OFFSET = 3; const int COMBO_UNFOLD_SELECT_WIDTH_MARGIN = 6; const int COMBO_UNFOLD_SELECT_HEIGHT_MARGIN = 4; const int COMBO_UNFOLD_SELECT_HEIGHT = 16; } using namespace KUI_MESSAGE; KUIControlCombo::KUIControlCombo() { m_bFold = true; m_bUpdate = true; m_itemWidth = 0; m_maxViewItemCount = COMBO_MAX_VIEW_LINE; m_selectItem = -1; m_preSelectItem = -1; m_pDownButton = NULL; m_pUnfoldBack = NULL; m_pUnfoldSelectBack = NULL; _registerPhrase(&m_ComboPhrase); } void KUIControlCombo::Render( KViewportObject *pViewport, bool isFront) { _UpdateComboItem(); KUIControl::Render(pViewport,isFront); } void KUIControlCombo::PumpUpMessage( LPCSTR lpszControlID, DWORD nMessage, DWORD lparam, DWORD wparam ) { switch ( nMessage ) { case KBUTTON_CLICK: { if( strcmp(lpszControlID,COMBO_BTN_ID ) == 0) { KUIControl::PumpUpMessage(GetID(), KCOMBO_CLICK, 0, 0); _SetFold(!m_bFold); } } break; default: break; } KUIControl::PumpUpMessage(lpszControlID,nMessage,lparam,wparam); } DWORD KUIControlCombo::OnMouseMessage(DWORD dwMessage,int x, int y) { if( IsDisable() ) return 0; // 펼처진 상태 if(m_bFold == false) { if(m_pUnfoldBack->GetRect().IsInRect(x,y)) { switch(dwMessage) { case KMOUSE_MOVE: _SetPreSelectItem(x,y); break; // Item을 선택했음 case KLBUTTON_UP: _SetPreSelectItem(x,y); if(m_selectItem != m_preSelectItem) { KUIControl::PumpUpMessage(GetID(), KCOMBO_CHANGE, m_selectItem, 0); } SetCurSel(m_preSelectItem); KUIControl::PumpUpMessage(GetID(), KCOMBO_SELECT, m_selectItem, 0); _SetFold(true); break; } } else if(false == m_rcRegion.IsInRect(x,y) ) { // 범위를 벗어나서 클릭하면 Fold 상태 if(dwMessage == KLBUTTON_UP) _SetFold(true); } } return KUIControl::OnMouseMessage(dwMessage,x,y); } bool KUIControlCombo::AddItem(LPCSTR itemName) { m_vtComboItems.push_back(itemName); m_bUpdate = true; return true; } bool KUIControlCombo::InsertItem(int index, LPCSTR lpszItem) { if(index >= m_vtComboItems.size() ) return false; m_vtComboItems.insert(m_vtComboItems.begin() + index, lpszItem); m_bUpdate = true; return true; } bool KUIControlCombo::RemoveItem(int index) { if(index >= m_vtComboItems.size() ) return false; m_vtComboItems.erase(m_vtComboItems.begin() + index); m_bUpdate = true; // 아이템이 지워졌으므로 예전 index가 바뀌므로 선택‰榮彭?다 취소 SetCurSel(-1); _SetPreSelectItem(-1); // Scroll Setting _SetScrollMaxRange(); return true; } int KUIControlCombo::FindItemIndex(LPCSTR itemName) { for(int i = 0; i < m_vtComboItems.size(); ++i) { if(m_vtComboItems.at(i) == itemName) return i; } return -1; } void KUIControlCombo::ClearItem() { m_vtComboItems.clear(); // 모든 아이템이 지워지면 선택도 못하게 되므로 SetCurSel(-1); _SetPreSelectItem(-1); m_bUpdate = true; } // Combo Item의 정렬 void KUIControlCombo::SetItemAlign(DWORD align) { m_ComboPhrase.SetAlign(align); m_bUpdate = true; } // Comobo Item의 최고 넒이 void KUIControlCombo::SetItemWidth(DWORD itemWidth) { m_itemWidth = itemWidth; m_bUpdate = true; } // 스크롤 없이 한번에 보여지는 Item의 갯수 void KUIControlCombo::SetMaxViewItem(DWORD maxViewCount) { m_maxViewItemCount = maxViewCount; m_bUpdate = true; } int KUIControlCombo::GetCount() { return m_vtComboItems.size(); } // 현재 선택된 Item을 알려줌 (선택된게 없으면 - 1을 리턴) int KUIControlCombo::GetCurSel() { return m_selectItem; } bool KUIControlCombo::SetCurSel(int index) { if(index >= GetCount() ) return false; // 이미 같은 걸로 선택되어 있으면 업데이트 할 필요 없음. if(m_selectItem == index) return true; m_selectItem = index; if(index < 0) SetCaption(m_sNotSelectedItem.c_str()); else SetCaption( m_vtComboItems.at(index).c_str() ); UpdateCaption(); return true; } void KUIControlCombo::_initControl() { if(m_sAniName.empty() ) m_sAniName = COMBO_FRAME_ANI_NAME; m_rcRegion.bottom = m_rcRegion.top + COMBO_ITEM_HEIGHT; UpdateBack(); int xSize = 0; KUITextureManager::GetManager()->GetSprAni( m_sSprName.c_str(), COMBO_BTN_ANI_NAME ); KResSprite * pFrame = _getSpriteSet()->GetSpriteRes(COMBO_BTN_ANI_NAME,0); if(pFrame) xSize = pFrame->GetSizeX(); m_itemWidth = GetRect().GetWidth() - xSize; // Back Ground Set m_rcCaptionArea.left += COMBO_LEFT_FRAME_WIDTH; m_rcCaptionArea.right -= xSize; m_dwCaptionAlign = KTextRender::KTALIGN_HCENTER | KTextRender::KTALIGN_VCENTER; UpdateCaption(); m_sNotSelectedItem = m_sCaption; // Down Button 초기화 KUIWND_CREATE_ARG CHILD_ARG; CHILD_ARG.pParent = this; CHILD_ARG.pWndManager = m_pManager; CHILD_ARG.lpszSprName = m_sSprName.c_str(); CHILD_ARG.lpszClassName = "simplebutton"; CHILD_ARG.lpszID = COMBO_BTN_ID; CHILD_ARG.lpszAniName = COMBO_BTN_ANI_NAME; CHILD_ARG.rcRect = KRect(GetRect().right - xSize - 2, GetRect().top + COMBO_BTN_Y_OFFSET,-1,-1); m_pDownButton = static_cast( m_pManager->CreateControl(CHILD_ARG) ); // UnFold Frame CHILD_ARG.lpszClassName = "static"; CHILD_ARG.lpszID = COMBO_UNFOLD_FRAME_ID; CHILD_ARG.lpszAniName = COMBO_UNFOLD_FRAME_ANI_NAME; CHILD_ARG.rcRect = KRect(GetRect().left, GetRect().bottom, GetRect().left + m_itemWidth, GetRect().bottom + _GetMaxViewLineHeight()); m_pUnfoldBack = static_cast( m_pManager->CreateControl(CHILD_ARG) ); KUITextureManager::GetManager()->GetSprAni( m_sSprName.c_str(), COMBO_UNFOLD_FRAME_ANI_NAME ); CHILD_ARG.lpszClassName = "static"; CHILD_ARG.lpszID = COMBO_UNFOLD_SELECT_ID; CHILD_ARG.lpszAniName = COMBO_UNFOLD_SELECT_ANI_NAME; CHILD_ARG.rcRect = KRect(GetRect().left, GetRect().bottom, GetRect().left + m_itemWidth, GetRect().bottom + _GetMaxViewLineHeight()); m_pUnfoldSelectBack = static_cast( m_pManager->CreateControl(CHILD_ARG) ); KUITextureManager::GetManager()->GetSprAni( m_sSprName.c_str(), COMBO_UNFOLD_SELECT_ANI_NAME ); // TextPhrse Initialize _InitComboPhrase(); _SetFold(true); } void KUIControlCombo::_InitComboPhrase() { m_ComboPhrase.Initialize(m_itemWidth, _GetMaxViewLineHeight()); m_ComboPhrase.SetAlign(KTextRender::KTALIGN_HCENTER | KTextRender::KTALIGN_TOP); m_ComboPhrase.SetPosition(GetRect().left, GetRect().bottom + COMBO_PHRASE_Y_OFFSET , m_fZPos); } void KUIControlCombo::_SetFold(bool bFold) { m_bFold = bFold; m_pUnfoldBack->SetShow(!bFold); m_pUnfoldSelectBack->SetShow(!bFold); m_ComboPhrase.SetVisibility(bFold ? 0.f : 1.f); } void KUIControlCombo::_UpdateComboItem() { // 접혀져 있는 상태이면 업데이트 할 필요가 없음. if(m_bFold || !m_bUpdate) return; std::vector::iterator it = m_vtComboItems.begin(); std::vector::iterator end = m_vtComboItems.end(); std::string sNewString = ""; // 아무것도 없는 경우 ==;; // disable 된거면 회색으로. -_- if( IsDisable() ) sNewString += "<#777777>"; int lineCount = 0; if(it == end) { sNewString += m_sNotSelectedItem; } else { while(1) { sNewString += *it; ++it; lineCount++; if( it == end) break; sNewString +="
"; } } // 새 Text를 textphrase에 셋팅 m_ComboPhrase.Clear(); _InitComboPhrase(); m_ComboPhrase.AddString(sNewString.c_str()); // 배경 Background를 알맞은 크기로 셋팅하자. KRect rcRect(GetRect() ); rcRect.top = GetRect().bottom + COMBO_UNFOLD_Y_OFFSET; rcRect.right = rcRect.left + m_itemWidth; #ifdef _COUNTRY_ME_ rcRect.bottom = rcRect.top + _GetUnfoldBackHeight(); //이 함수가 오작동함 (지나치게 큰 값을 리턴) 그래서 다시 구함 #else DWORD dwStringWidth, dwStringHeight; #ifdef _COUNTRY_TL_ dwStringHeight = 16; // 하드코딩 -_- #else KTextRender::GetStringSize("default", 10, false, "ABC123", 6,&dwStringWidth, &dwStringHeight); #endif rcRect.bottom = rcRect.top + (dwStringHeight + 3) * lineCount + 3; #endif m_pUnfoldBack->SetRect(rcRect); m_pUnfoldBack->UpdateBack(); // Scroll을 알맞은 Range로 셋팅 _SetScrollMaxRange(); _SetPreSelectItem(m_preSelectItem); m_bUpdate = false; } int KUIControlCombo::_GetUnfoldBackHeight() { int totalHeight = min( m_ComboPhrase.GetTotalLineHeigt(), _GetMaxViewLineHeight() ); return (totalHeight + COMBO_UNFOLD_Y_ADD_HEIGHT); } void KUIControlCombo::_SetPreSelectItem(int x, int y) { if(m_vtComboItems.size() == 0) { _SetPreSelectItem(-1); } else { int itemCount = m_vtComboItems.size(); int backHegiht = m_pUnfoldBack->GetRect().GetHeight(); int offset = y - m_pUnfoldBack->GetRect().top; float fRatio = static_cast( offset) / static_cast( backHegiht ); int index = fRatio * itemCount; index = max(index,0); index = min(index,itemCount - 1); _SetPreSelectItem(index); //if(_IsScrollEnable() ) //{ // m_preSelectItem += m_pComboScroll->GetPosition(); //} } } void KUIControlCombo::_SetPreSelectItem(int index) { int addHeight = 0; KRect rcRect(0,0,0,0); if(index < 0) { m_preSelectItem = -1; } else if( false == m_vtComboItems.empty() ) { m_preSelectItem = index; int itemCount = m_vtComboItems.size(); int backHegiht = m_pUnfoldBack->GetRect().GetHeight(); int heightPerItem = (backHegiht - 3) / itemCount; // 저 위에서 m_pUnfoldBack 높이에 3을 더했으니 3을 •弧? addHeight = m_preSelectItem * heightPerItem; rcRect.left = GetRect().left; rcRect.top = m_pUnfoldBack->GetRect().top + addHeight + COMBO_UNFOLD_SELECT_Y_OFFSET; rcRect.right = rcRect.left + m_itemWidth; rcRect.bottom = rcRect.top + COMBO_UNFOLD_SELECT_HEIGHT; rcRect.left += COMBO_UNFOLD_SELECT_WIDTH_MARGIN / 2; rcRect.right -= COMBO_UNFOLD_SELECT_WIDTH_MARGIN / 2; rcRect.top += COMBO_UNFOLD_SELECT_HEIGHT_MARGIN / 2 - 3; // 위치조정을 위해 살짝 -3 rcRect.bottom -= COMBO_UNFOLD_SELECT_HEIGHT_MARGIN / 2; } m_pUnfoldSelectBack->SetRect(rcRect); m_pUnfoldSelectBack->UpdateBack(); } void KUIControlCombo::OnChangeCaptionNotify() { if( !IsDisable() ) { size_t cpos = 0; while( ( cpos = m_sCaption.find( "<#" ) ) != m_sCaption.npos ) { m_sCaption.erase( cpos, 9 ); } std::string strNewCaption = m_strEnableColor.c_str(); strNewCaption += m_sCaption; m_sCaption = strNewCaption; } KUIControl::OnChangeCaptionNotify(); } bool KUIControlCombo::_IsScrollEnable() { return m_vtComboItems.size() > m_maxViewItemCount; } void KUIControlCombo::_SetScrollMaxRange() { //if(_IsScrollEnable() ) //{ // m_pComboScroll->SetMaxRange( m_vtComboItems.size() - m_maxViewItemCount + 1 ); //} } DWORD KUIControlCombo::_GetMaxViewLineHeight() { return COMBO_TEXT_HEIGHT * m_maxViewItemCount + COMBO_TEXT_GAP * (m_maxViewItemCount - 1); }