00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "CtrlSchema.h"
00025 #include "Schema.h"
00026 #include "XML.h"
00027 #include "Skin.h"
00028
00029 #ifdef _DEBUG
00030 #define new DEBUG_NEW
00031 #undef THIS_FILE
00032 static char THIS_FILE[] = __FILE__;
00033 #endif
00034
00035 BEGIN_MESSAGE_MAP(CSchemaCtrl, CWnd)
00036
00037 ON_WM_ERASEBKGND()
00038 ON_WM_CREATE()
00039 ON_WM_DESTROY()
00040 ON_WM_PAINT()
00041 ON_WM_VSCROLL()
00042 ON_WM_SIZE()
00043 ON_WM_NCPAINT()
00044 ON_WM_SETFOCUS()
00045 ON_WM_LBUTTONDOWN()
00046 ON_WM_MOUSEWHEEL()
00047
00048 ON_EN_CHANGE(IDC_METADATA_CONTROL, OnControlEdit)
00049 ON_CBN_SELCHANGE(IDC_METADATA_CONTROL, OnControlEdit)
00050 ON_CBN_EDITCHANGE(IDC_METADATA_CONTROL, OnControlEdit)
00051 END_MESSAGE_MAP()
00052
00054
00055
00056 CSchemaCtrl::CSchemaCtrl()
00057 {
00058 CString strText;
00059 LoadString( strText, IDS_MULTIPLE_VALUES );
00060 strMultipleString = _T("(") + strText + _T(")");
00061 m_nCaptionWidth = 120;
00062 m_nItemHeight = 32;
00063 m_bShowBorder = TRUE;
00064 m_pSchema = NULL;
00065 m_nScroll = 0;
00066
00067
00068 if( !SystemParametersInfo ( SPI_GETWHEELSCROLLLINES, 0, &m_nScrollWheelLines, 0) )
00069 {
00070 m_nScrollWheelLines = 3;
00071 }
00072 }
00073
00074 CSchemaCtrl::~CSchemaCtrl()
00075 {
00076 }
00077
00079
00080
00081 BOOL CSchemaCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
00082 {
00083 dwStyle |= WS_CHILD|WS_VSCROLL|WS_CLIPCHILDREN;
00084 DWORD dwExStyle = theApp.m_bRTL ? WS_EX_LAYOUTRTL : 0;
00085 return CWnd::CreateEx( dwExStyle, NULL, NULL, dwStyle, rect, pParentWnd, nID, NULL );
00086 }
00087
00088 int CSchemaCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
00089 {
00090 if ( CWnd::OnCreate( lpCreateStruct ) == -1 ) return -1;
00091 return 0;
00092 }
00093
00094 void CSchemaCtrl::OnDestroy()
00095 {
00096 SetSchema( NULL );
00097 CWnd::OnDestroy();
00098 }
00099
00100 void CSchemaCtrl::OnSize(UINT nType, int cx, int cy)
00101 {
00102 CWnd::OnSize( nType, cx, cy );
00103 m_nScroll = 0;
00104 Invalidate();
00105 Layout();
00106 }
00107
00109
00110
00111 void CSchemaCtrl::SetSchema(CSchema* pSchema, BOOL bPromptOnly)
00112 {
00113 CObArray pRemove;
00114 pRemove.Append( m_pControls );
00115
00116 m_pControls.RemoveAll();
00117 m_pCaptions.RemoveAll();
00118
00119 for ( int nControl = 0 ; nControl < pRemove.GetSize() ; nControl++ )
00120 {
00121 CWnd* pControl = (CWnd*)pRemove.GetAt( nControl );
00122 pControl->DestroyWindow();
00123 delete pControl;
00124 }
00125
00126 m_nScroll = 0;
00127
00128 if ( ! ( m_pSchema = pSchema ) )
00129 {
00130 Layout();
00131 Invalidate();
00132 return;
00133 }
00134
00135 for ( POSITION pos = pSchema->GetMemberIterator() ; pos ; )
00136 {
00137 CSchemaMember* pMember = pSchema->GetNextMember( pos );
00138
00139 if ( bPromptOnly && ! pMember->m_bPrompt ) continue;
00140
00141 CWnd* pControl = NULL;
00142 CRect rc;
00143
00144 if ( pMember->GetItemCount() )
00145 {
00146 CComboBox* pCombo = new CComboBox();
00147
00148 pCombo->Create( WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP|CBS_DROPDOWN|
00149 CBS_AUTOHSCROLL|WS_VSCROLL, rc, this, IDC_METADATA_CONTROL );
00150
00151 for ( POSITION pos = pMember->GetItemIterator() ; pos ; )
00152 {
00153 CString strSelection = pMember->GetNextItem( pos );
00154 pCombo->AddString( strSelection );
00155 }
00156
00157 pControl = pCombo;
00158 }
00159 else
00160 {
00161 CEdit* pEdit = new CEdit();
00162 pEdit->Create( WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,
00163 rc, this, IDC_METADATA_CONTROL );
00164 pEdit->ModifyStyleEx( 0, WS_EX_CLIENTEDGE );
00165 if ( pMember->m_nMaxLength ) pEdit->LimitText( pMember->m_nMaxLength );
00166 pControl = pEdit;
00167 }
00168
00169 CString strCaption = pMember->m_sTitle + ':';
00170
00171 m_pCaptions.Add( strCaption );
00172 m_pControls.Add( pControl );
00173
00174 SetWindowLong( pControl->GetSafeHwnd(), GWL_USERDATA, (LONG)pMember );
00175 pControl->SetFont( &theApp.m_gdiFont );
00176 }
00177
00178 Layout();
00179 Invalidate();
00180 }
00181
00183
00184
00185 BOOL CSchemaCtrl::UpdateData(CXMLElement* pBase, BOOL bSaveAndValidate)
00186 {
00187 if ( m_pSchema == NULL || pBase == NULL ) return FALSE;
00188
00189 if ( pBase->GetName().CompareNoCase( m_pSchema->m_sSingular ) ) return FALSE;
00190
00191 POSITION pos = m_pSchema->GetMemberIterator();
00192
00193 for ( int nControl = 0 ; nControl < m_pControls.GetSize() && pos ; nControl++ )
00194 {
00195 CWnd* pControl = (CWnd*)m_pControls.GetAt( nControl );
00196 CSchemaMember* pMember = NULL;
00197 CString strValue;
00198
00199 while ( pos )
00200 {
00201 pMember = m_pSchema->GetNextMember( pos );
00202 if ( (LONG)pMember == GetWindowLong( pControl->GetSafeHwnd(), GWL_USERDATA ) ) break;
00203 pMember = NULL;
00204 }
00205
00206 if ( pMember == NULL ) break;
00207
00208 if ( bSaveAndValidate )
00209 {
00210 pControl->GetWindowText( strValue );
00211
00212 if ( strValue != strMultipleString )
00213 pMember->SetValueTo( pBase, strValue );
00214 }
00215 else
00216 {
00217 strValue = pMember->GetValueFrom( pBase );
00218
00219 if ( strValue == _T("(~mt~)") )
00220 {
00221 pControl->SetWindowText( strMultipleString );
00222 }
00223 else
00224 {
00225 pControl->SetWindowText( strValue );
00226 }
00227 }
00228 }
00229
00230 return TRUE;
00231 }
00232
00234
00235
00236 void CSchemaCtrl::Layout()
00237 {
00238 CRect rcClient, rcNew;
00239 SCROLLINFO pScroll;
00240
00241 GetClientRect( &rcClient );
00242
00243 ZeroMemory( &pScroll, sizeof(pScroll) );
00244 pScroll.cbSize = sizeof(pScroll);
00245 pScroll.fMask = SIF_PAGE|SIF_POS|SIF_RANGE;
00246 pScroll.nPage = rcClient.Height();
00247 pScroll.nPos = m_nScroll;
00248
00249 HDWP hDWP = BeginDeferWindowPos( m_pControls.GetSize() );
00250
00251 int nTop = -m_nScroll;
00252
00253 for ( int nControl = 0 ; nControl < m_pControls.GetSize() ; nControl++ )
00254 {
00255 CWnd* pControl = (CWnd*)m_pControls.GetAt( nControl );
00256
00257 if ( m_nCaptionWidth )
00258 {
00259 if ( theApp.m_bRTL )
00260 {
00261 rcNew.left = m_nCaptionWidth;
00262 rcNew.right = rcClient.right - 10;
00263 }
00264 else
00265 {
00266 rcNew.left = m_nCaptionWidth;
00267 rcNew.right = rcClient.right - 10;
00268 }
00269 rcNew.top = nTop + m_nItemHeight / 2 - 9;
00270 rcNew.bottom = nTop + m_nItemHeight / 2 + 9;
00271 }
00272 else
00273 {
00274 rcNew.left = rcClient.left + 4;
00275 rcNew.right = rcClient.right - 4;
00276 rcNew.top = nTop + m_nItemHeight - 18 - 4;
00277 rcNew.bottom = nTop + m_nItemHeight - 4;
00278 }
00279
00280 if ( pControl->IsKindOf( RUNTIME_CLASS( CComboBox ) ) )
00281 {
00282 rcNew.top --;
00283 rcNew.bottom += 128;
00284 }
00285
00286 hDWP = DeferWindowPos( hDWP, pControl->GetSafeHwnd(), NULL, rcNew.left, rcNew.top,
00287 rcNew.Width(), rcNew.Height(), SWP_SHOWWINDOW|SWP_NOACTIVATE );
00288
00289 pScroll.nMax += m_nItemHeight;
00290 nTop += m_nItemHeight;
00291 }
00292
00293 EndDeferWindowPos( hDWP );
00294
00295 pScroll.nMax--;
00296 SetScrollInfo( SB_VERT, &pScroll );
00297 }
00298
00300
00301
00302 void CSchemaCtrl::Disable()
00303 {
00304 if ( m_pSchema == NULL ) return;
00305
00306 POSITION pos = m_pSchema->GetMemberIterator();
00307
00308 for ( int nControl = 0 ; nControl < m_pControls.GetSize() && pos ; nControl++ )
00309 {
00310 ((CWnd *)m_pControls.GetAt( nControl ))->EnableWindow( FALSE );
00311 }
00312
00313 return;
00314 }
00315
00316
00318
00319
00320 void CSchemaCtrl::Enable()
00321 {
00322 if ( m_pSchema == NULL ) return;
00323
00324 POSITION pos = m_pSchema->GetMemberIterator();
00325
00326 for ( int nControl = 0 ; nControl < m_pControls.GetSize() && pos ; nControl++ )
00327 {
00328 ((CWnd *)m_pControls.GetAt( nControl ))->EnableWindow( TRUE );
00329 }
00330
00331 return;
00332 }
00333
00334
00336
00337
00338 void CSchemaCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00339 {
00340 SCROLLINFO pScroll;
00341
00342 ZeroMemory( &pScroll, sizeof(pScroll) );
00343 pScroll.cbSize = sizeof(pScroll);
00344 pScroll.fMask = SIF_ALL;
00345
00346 GetScrollInfo( SB_VERT, &pScroll );
00347
00348 switch ( nSBCode )
00349 {
00350 case SB_TOP:
00351 m_nScroll = 0;
00352 break;
00353 case SB_BOTTOM:
00354 m_nScroll = pScroll.nMax - 1;
00355 break;
00356 case SB_LINEUP:
00357 m_nScroll -= 8;
00358 break;
00359 case SB_LINEDOWN:
00360 m_nScroll += 8;
00361 break;
00362 case SB_PAGEUP:
00363 m_nScroll -= pScroll.nPage;
00364 break;
00365 case SB_PAGEDOWN:
00366 m_nScroll += pScroll.nPage;
00367 break;
00368 case SB_THUMBPOSITION:
00369 case SB_THUMBTRACK:
00370 m_nScroll = nPos;
00371 break;
00372 }
00373
00374 int nDelta = m_nScroll - pScroll.nPos;
00375 m_nScroll = pScroll.nPos;
00376
00377 ScrollBy( nDelta );
00378 }
00379
00380 void CSchemaCtrl::ScrollBy(int nDelta)
00381 {
00382 int nBefore = m_nScroll;
00383
00384 m_nScroll += nDelta;
00385 m_nScroll = max( 0, min( GetScrollLimit( SB_VERT ), m_nScroll ) );
00386 nDelta = m_nScroll - nBefore;
00387
00388 for ( CWnd* pWnd = GetWindow( GW_CHILD ) ; pWnd ; pWnd = pWnd->GetNextWindow() )
00389 {
00390 pWnd->ModifyStyle( WS_VISIBLE, 0 );
00391 }
00392
00393 ScrollWindowEx( 0, -nDelta, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN|SW_INVALIDATE );
00394 Layout();
00395 UpdateWindow();
00396 }
00397
00398 void CSchemaCtrl::OnLButtonDown(UINT nFlags, CPoint point)
00399 {
00400 SetFocus();
00401 }
00402
00403 BOOL CSchemaCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
00404 {
00405 OnVScroll( SB_THUMBPOSITION, (int)( GetScrollPos( SB_VERT ) - zDelta / WHEEL_DELTA * m_nScrollWheelLines * 8 ), NULL );
00406 return TRUE;
00407 }
00408
00410
00411
00412 BOOL CSchemaCtrl::OnEraseBkgnd(CDC* pDC)
00413 {
00414 return TRUE;
00415 }
00416
00417 void CSchemaCtrl::OnNcPaint()
00418 {
00419 CWnd::OnNcPaint();
00420
00421 if ( m_bShowBorder )
00422 {
00423 CWindowDC dc( this );
00424 CRect rc;
00425
00426 COLORREF crBorder = GetSysColor( COLOR_ACTIVECAPTION );
00427
00428 GetWindowRect( &rc );
00429 rc.OffsetRect( -rc.left, -rc.top );
00430 dc.Draw3dRect( &rc, crBorder, crBorder );
00431 }
00432 }
00433
00434 void CSchemaCtrl::OnPaint()
00435 {
00436 CRect rcClient, rcItem;
00437 CPaintDC dc( this );
00438
00439 GetClientRect( &rcClient );
00440 rcItem.CopyRect( &rcClient );
00441
00442 rcItem.bottom = rcItem.top + m_nItemHeight;
00443 rcItem.OffsetRect( 0, -m_nScroll );
00444
00445 CFont* pOldFont = (CFont*)dc.SelectObject( &theApp.m_gdiFont );
00446 dc.SetBkMode( OPAQUE );
00447
00448 int nOffset = m_nItemHeight;
00449
00450 if ( ! m_nCaptionWidth ) nOffset -= 18 + 4;
00451
00452 nOffset = nOffset / 2 - dc.GetTextExtent( _T("Xg") ).cy / 2 - 1;
00453
00454 for ( int nControl = 0 ; nControl < m_pControls.GetSize() ; nControl++ )
00455 {
00456
00457 dc.SetBkColor( Skin.m_crSchemaRow[ nControl & 1 ] );
00458
00459 dc.ExtTextOut( rcItem.left + 4, rcItem.top + nOffset, ETO_OPAQUE|ETO_CLIPPED,
00460 &rcItem, m_pCaptions.GetAt( nControl ), NULL );
00461
00462 rcItem.OffsetRect( 0, m_nItemHeight );
00463 }
00464
00465 if ( rcItem.top < rcClient.bottom )
00466 {
00467 rcItem.SetRect( rcClient.left, rcItem.top, rcClient.right, rcClient.bottom );
00468 dc.FillSolidRect( &rcItem, GetSysColor( COLOR_WINDOW ) );
00469 }
00470
00471 dc.SelectObject( pOldFont );
00472 }
00473
00475
00476
00477 BOOL CSchemaCtrl::OnTab()
00478 {
00479 CWnd* pFocus = GetFocus();
00480 CWnd* pPrevious = NULL;
00481
00482 BOOL bShift = GetAsyncKeyState( VK_SHIFT ) & 0x8000;
00483 BOOL bNext = FALSE;
00484
00485 if ( pFocus == GetWindow( GW_HWNDPREV ) )
00486 {
00487 if ( bShift ) return FALSE;
00488 bNext = TRUE;
00489 }
00490
00491 for ( int nControl = 0 ; nControl < m_pControls.GetSize() ; nControl++ )
00492 {
00493 CWnd* pControl = (CWnd*)m_pControls.GetAt( nControl );
00494
00495 if ( bNext )
00496 {
00497 SetFocusTo( pControl );
00498 return TRUE;
00499 }
00500 else if ( pControl == pFocus || pControl->GetWindow( GW_CHILD ) == pFocus )
00501 {
00502 if ( bShift )
00503 {
00504 if ( pPrevious )
00505 {
00506 SetFocusTo( pPrevious );
00507 return TRUE;
00508 }
00509 else
00510 {
00511 pFocus = GetWindow( GW_HWNDPREV );
00512 if ( pFocus ) pFocus->SetFocus();
00513 return TRUE;
00514 }
00515 }
00516 else
00517 {
00518 bNext = TRUE;
00519 }
00520 }
00521
00522 pPrevious = pControl;
00523 }
00524
00525 if ( bNext )
00526 {
00527 pFocus = GetWindow( GW_HWNDNEXT );
00528 if ( pFocus == NULL ) GetWindow( GW_HWNDFIRST );
00529 if ( pFocus ) pFocus->SetFocus();
00530 return TRUE;
00531 }
00532
00533 return FALSE;
00534 }
00535
00536 void CSchemaCtrl::SetFocusTo(CWnd* pControl)
00537 {
00538 CRect rcClient, rcControl;
00539
00540 GetClientRect( &rcClient );
00541 pControl->GetWindowRect( &rcControl );
00542 ScreenToClient( &rcControl );
00543
00544 if ( rcControl.top < rcClient.top )
00545 {
00546 ScrollBy( rcControl.top - rcClient.top - 8 );
00547 }
00548 else if ( rcControl.bottom > rcClient.bottom )
00549 {
00550 ScrollBy( rcControl.bottom - rcClient.bottom + 8 );
00551 }
00552
00553 pControl->SetFocus();
00554 }
00555
00557
00558
00559 BOOL CSchemaCtrl::OnCommand(WPARAM wParam, LPARAM lParam)
00560 {
00561 if ( HIWORD( wParam ) != EN_CHANGE ) return CWnd::OnCommand( wParam, lParam );
00562
00563 CEdit* pEdit = (CEdit*)CWnd::FromHandle( (HWND)lParam );
00564 if ( ! pEdit->IsKindOf( RUNTIME_CLASS(CEdit) ) ) return TRUE;
00565
00566 CSchemaMember* pMember = (CSchemaMember*)GetWindowLong( (HWND)lParam, GWL_USERDATA );
00567
00568 if ( pMember->m_bNumeric )
00569 {
00570 CString strTextIn, strTextOut;
00571 BOOL bChanged = FALSE;
00572
00573 pEdit->GetWindowText( strTextIn );
00574
00575 if ( strTextIn != strMultipleString )
00576 {
00577 LPTSTR pszOut = strTextOut.GetBuffer( strTextIn.GetLength() );
00578
00579 for ( LPCTSTR pszIn = strTextIn ; *pszIn ; pszIn++ )
00580 {
00581 if ( ( *pszIn >= '0' && *pszIn <= '9' ) || *pszIn == '.' || *pszIn == '-' )
00582 {
00583 *pszOut++ = *pszIn;
00584 }
00585 else bChanged = TRUE;
00586 }
00587
00588 *pszOut = 0;
00589 strTextOut.ReleaseBuffer();
00590 }
00591
00592 if ( bChanged )
00593 {
00594 pEdit->SetWindowText( strTextOut );
00595 pEdit->SetSel( strTextOut.GetLength(), strTextOut.GetLength() );
00596 }
00597 }
00598
00599 return CWnd::OnCommand( wParam, lParam );
00600 }
00601
00602 void CSchemaCtrl::OnSetFocus(CWnd* pOldWnd)
00603 {
00604 CWnd::OnSetFocus( pOldWnd );
00605
00606 if ( m_pControls.GetSize() > 0 )
00607 {
00608 CWnd* pWnd = (CWnd*)m_pControls.GetAt( 0 );
00609 SetFocusTo( pWnd );
00610 }
00611 }
00612
00613 void CSchemaCtrl::OnControlEdit()
00614 {
00615 GetOwner()->SendMessage( WM_COMMAND, MAKELONG( GetDlgCtrlID(), EN_CHANGE ), (LPARAM)GetSafeHwnd() );
00616 }