Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

CtrlSchema.cpp

Go to the documentation of this file.
00001 //
00002 // CtrlSchema.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         //{{AFX_MSG_MAP(CSchemaCtrl)
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         //}}AFX_MSG_MAP
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 // CSchemaCtrl construction
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         // Try to get the number of lines to scroll when the mouse wheel is rotated
00068         if( !SystemParametersInfo ( SPI_GETWHEELSCROLLLINES, 0, &m_nScrollWheelLines, 0) )
00069         {
00070                 m_nScrollWheelLines = 3;
00071         }
00072 }
00073 
00074 CSchemaCtrl::~CSchemaCtrl()
00075 {
00076 }
00077 
00079 // CSchemaCtrl create and destroy
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 // CSchemaCtrl schema selection
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 // CSchemaCtrl data transfer
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 // CSchemaCtrl child control layout
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 // CSchemaCtrl disable
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 // CSchemaCtrl enable
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 // CSchemaCtrl scrolling
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 // CSchemaCtrl painting
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                 // dc.SetBkColor( nControl & 1 ? RGB( 240, 240, 255 ) : RGB( 255, 255, 255 ) );
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 // CSchemaCtrl focus movement
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 // CSchemaCtrl command handler
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 }

Generated on Thu Dec 15 10:39:37 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2