home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- #include "stdafx.h"
- #include "DateEdit.h"
-
-
- #ifdef DEBUG_mitch
- #define DEBUGONLY( stmt ) stmt;
- #define DEBUGOUT(s) OutputDebugString(s)
- #else
- #define DEBUGONLY( stmt ) ;
- #define DEBUGOUT(s)
- #endif
-
- #ifdef DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define ID_DAY 101
- #define ID_MONTH 102
- #define ID_YEAR 103
-
- static int _GetMonthDays(int nYear, int nMonth)
- {
- static int cDaysInMonth[] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
-
- if( nYear % 100 != 0 && nYear % 4 == 0 && nMonth == 2)
- return 29;
-
- return cDaysInMonth[nMonth - 1];
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CNSDateEdit public API
-
-
- //=============================================================== CNSDateEdit
- CNSDateEdit::CNSDateEdit()
- {
- m_bNeedControls = TRUE;
- m_nDay = m_nMonth = m_nYear = 0;
- m_iCurrentField = 0;
- m_pFields[0] = m_pFields[1] = m_pFields[2] = NULL;
- }
-
-
- //============================================================== ~CNSDateEdit
- CNSDateEdit::~CNSDateEdit()
- {
- }
-
-
- //=================================================================== SetDate
- BOOL CNSDateEdit::SetDate( CTime &d )
- {
- return SetDate( d.GetYear(), d.GetMonth(), d.GetDay() );
- }
-
-
- //=================================================================== SetDate
- BOOL CNSDateEdit::SetDate( int nYear, int nMonth, int nDay )
- {
- m_nDay = nDay;
- m_nMonth = nMonth;
- m_nYear = nYear;
- if ( !m_bNeedControls )
- {
- m_DayField.SetValue( m_nDay );
- m_MonthField.SetValue( m_nMonth );
- m_YearField.SetValue( m_nYear );
- }
- return TRUE;
- }
-
-
- //=================================================================== GetDate
- BOOL CNSDateEdit::GetDate( CTime &d )
- {
- int nYear, nMonth, nDay;
- if ( !GetDate( nYear, nMonth, nDay ) )
- return FALSE;
- d = CTime( nYear, nMonth, nDay, 0, 0, 0 );
- return TRUE;
- }
-
-
- //=================================================================== GetDate
- BOOL CNSDateEdit::GetDate( int &nYear, int &nMonth, int &nDay )
- {
- if (Validate()) {
- nYear = m_nYear;
- nMonth = m_nMonth;
- nDay = m_nDay;
-
- return TRUE;
- }
- return FALSE;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CNSDateEdit message handlers
-
- BEGIN_MESSAGE_MAP(CNSDateEdit, CStatic)
- ON_WM_PAINT()
- ON_WM_SETFOCUS()
- ON_WM_SIZE()
- ON_WM_ENABLE()
- ON_WM_GETDLGCODE()
- ON_EN_MAXTEXT(ID_DAY, OnMaxText)
- ON_EN_MAXTEXT(ID_MONTH, OnMaxText)
- ON_EN_MAXTEXT(ID_YEAR, OnMaxText)
- ON_EN_SETFOCUS(ID_DAY, OnFocusDay)
- ON_EN_SETFOCUS(ID_MONTH, OnFocusMonth)
- ON_EN_SETFOCUS(ID_YEAR, OnFocusYear)
- ON_EN_KILLFOCUS(ID_DAY, OnKillFocusDay)
- ON_EN_KILLFOCUS(ID_MONTH, OnKillFocusMonth)
- ON_EN_KILLFOCUS(ID_YEAR, OnKillFocusYear)
- ON_MESSAGE(NSDE_RELAYEVENT, OnRelayEvent)
- END_MESSAGE_MAP()
-
-
- //=================================================================== OnPaint
- void CNSDateEdit::OnPaint()
- {
- ASSERT( IsWindow( m_hWnd ) );
-
- char szSeparator[2];
- #ifdef WIN32
- VERIFY( GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SDATE, szSeparator, 2 ) == 2 );
- #else
- static char cName [] = "intl" ;
- GetProfileString (cName, "sDate", "/", szSeparator, 2) ;
- #endif
-
- BOOL bEnabled = IsWindowEnabled();
- CPaintDC dc(this);
- CBrush winBrush( GetSysColor( bEnabled ? COLOR_WINDOW : COLOR_BTNFACE ) );
- dc.FillRect( &dc.m_ps.rcPaint, &winBrush );
-
- if ( m_bNeedControls )
- CreateSubWindows( );
-
- CFont *pOldFont = dc.SelectObject( CFont::FromHandle( (HFONT)::GetStockObject( ANSI_VAR_FONT ) ) );
- int oldMode = dc.SetBkMode( TRANSPARENT );
- COLORREF oldTextColor = dc.SetTextColor( GetSysColor( bEnabled ? COLOR_BTNTEXT : COLOR_GRAYTEXT ) );
-
- dc.DrawText( szSeparator, -1, m_Sep1, DT_SINGLELINE | DT_CENTER | DT_VCENTER );
- dc.DrawText( szSeparator, -1, m_Sep2, DT_SINGLELINE | DT_CENTER | DT_VCENTER );
-
- dc.SelectObject( pOldFont );
- dc.SetBkMode( oldMode );
- dc.SetTextColor( oldTextColor );
- }
-
-
- void CNSDateEdit::OnSetFocus(CWnd* pOldWnd)
- {
- if ( m_bNeedControls )
- CreateSubWindows( );
-
- m_pFields[0]->SetFocus();
- m_iCurrentField = 0;
- }
-
- void CNSDateEdit::OnSize( UINT nType, int cx, int cy )
- {
- if ( m_bNeedControls )
- CreateSubWindows( );
-
- if ( nType != SIZE_MINIMIZED ) {
- RECT r;
- ::SetRect( &r, 0, 0, cx, cy );
- LayoutSubWindows( &r );
- }
- }
-
- void CNSDateEdit::OnEnable( BOOL bEnable )
- {
- if ( m_bNeedControls )
- CreateSubWindows( );
-
- m_YearField.EnableWindow( bEnable );
- m_MonthField.EnableWindow( bEnable );
- m_DayField.EnableWindow( bEnable );
-
- CStatic::OnEnable( bEnable );
-
- Invalidate();
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CNSDateEdit protected & private methods
-
-
- //========================================================== CreateSubWindows
- void CNSDateEdit::CreateSubWindows( )
- {
- m_bNeedControls = FALSE;
-
- RECT r, rcClient;
-
- ::SetRectEmpty(&r);
- GetClientRect( &rcClient );
-
- VERIFY( m_YearField.Create( WS_VISIBLE, r, this, (UINT)ID_YEAR ) );
- m_YearField.LimitText( 4 );
-
- if ( m_nYear != 0 )
- m_YearField.SetValue( m_nYear );
-
- VERIFY( m_MonthField.Create( WS_VISIBLE, r, this, (UINT)ID_MONTH ) );
- m_MonthField.LimitText( 2 );
- if ( m_nMonth != 0 )
- m_MonthField.SetValue( m_nMonth );
-
- VERIFY( m_DayField.Create( WS_VISIBLE, r, this, (UINT)ID_DAY ) );
- m_DayField.LimitText( 2 );
- if ( m_nDay != 0 )
- m_DayField.SetValue( m_nDay );
-
- m_wndSpin.Create(UDS_WRAP|UDS_ARROWKEYS|UDS_SETBUDDYINT|UDS_NOTHOUSANDS|WS_CHILD|WS_VISIBLE,
- CRect(0,0,0,0), this, 104 );
-
- LayoutSubWindows( &rcClient );
-
- m_wndSpin.SetBuddy(m_pFields[0]);
- if (m_pFields[0] == &m_DayField) {
- int nDays = _GetMonthDays(m_nYear, m_nMonth);
- m_wndSpin.SetRange(1, nDays);
- m_wndSpin.SetPos(m_nDay);
- } else if (m_pFields[0] == &m_MonthField) {
- m_wndSpin.SetRange(1, 12);
- m_wndSpin.SetPos(m_nMonth);
- } else {
- m_wndSpin.SetRange(1970, 2037);
- m_wndSpin.SetPos(m_nMonth);
- }
- }
-
- void CNSDateEdit::LayoutSubWindows( RECT *pRect )
- {
- HDC hDC = ::GetDC( m_hWnd );
- ASSERT( hDC );
-
- int w = pRect->right - pRect->left;
- RECT r, rcSep, rcNum;
- TCHAR szSeparator[2], szFormat[30], *s;
- HFONT hFont = (HFONT)::GetStockObject( ANSI_VAR_FONT );
- CFont *fontCur = CFont::FromHandle( hFont );
-
- LOGFONT lf;
- GetObject( hFont, sizeof(lf), &lf);
-
- // Get locale info
- #ifdef WIN32
- VERIFY( GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, szFormat, 30 ) > 0 );
- VERIFY( GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SDATE, szSeparator, 2 ) > 0 );
- #else
- static char cName [] = "intl" ;
- GetProfileString (cName, "sDate", "/", szSeparator, 2) ;
-
- int iDate = GetProfileInt (cName, "iDate", 0) ;
- sprintf( szFormat, "%c%s%c%s%c",
- iDate == 1 ? 'd' : iDate == 2 ? 'y' : 'M', szSeparator,
- iDate == 1 ? 'M' : iDate == 2 ? 'M' : 'd', szSeparator,
- iDate == 1 ? 'y' : iDate == 2 ? 'd' : 'y' );
- #endif
-
- // Get font info
- ::SetRectEmpty(&rcSep);
- ::SetRectEmpty(&rcNum);
-
- DrawText( hDC, szSeparator, -1, &rcSep,
- DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_CALCRECT );
- DrawText( hDC, _T("0"), -1, &rcNum,
- DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_CALCRECT );
-
- ASSERT( w >= ( rcSep.right * 2 + rcNum.right * 8 ) );
-
- // Start on the left
-
- int iHeight = lf.lfHeight;
- int iWidth = 0;
-
- r.top = pRect->top - ((pRect->top-pRect->bottom)+iHeight)/2 - 1;
- r.bottom = r.top + iHeight + 2;
-
- r.right = pRect->left + 1;
-
- // this loop parses the short date format, creating the fields as it goes
- s = strtok( szFormat, szSeparator );
- for( int i = 0; (i < 3) && (s != NULL); i++ )
- {
- switch ( s[0] )
- {
- case 'M':
- case 'm':
- r.left = r.right + 1;
- r.right = r.left + rcNum.right * 2 + iWidth; // room for two characters
- m_MonthField.MoveWindow( &r );
- m_MonthField.SetFont( fontCur );
- m_pFields[i] = &m_MonthField;
- break;
- case 'Y':
- case 'y':
- r.left = r.right + 1;
- r.right = r.left + rcNum.right * 4 + iWidth; // room for four characters
- m_YearField.MoveWindow( &r );
- m_YearField.SetFont( fontCur );
- m_pFields[i] = &m_YearField;
- break;
- case 'D':
- case 'd':
- r.left = r.right + 1;
- r.right = r.left + rcNum.right * 2 + iWidth; // room for two characters
- m_DayField.MoveWindow( &r );
- m_DayField.SetFont( fontCur );
- m_pFields[i] = &m_DayField;
- break;
- default:
- DebugBreak();
- }
- if ( i == 0 )
- {
- r.left = r.right + 1;
- r.right = r.left + rcSep.right;
- m_Sep1 = r;
- }
- else if ( i == 1 )
- {
- r.left = r.right + 1;
- r.right = r.left + rcSep.right;
- m_Sep2 = r;
- }
-
- s = strtok( NULL, szSeparator );
- }
-
- r = *pRect;
- r.left = r.right - GetSystemMetrics(SM_CXVSCROLL);
-
- m_wndSpin.MoveWindow(&r);
-
- ::ReleaseDC( m_hWnd, hDC );
- }
-
- //================================================================ Validate
- BOOL CNSDateEdit::Validate()
- {
- int nYear = m_YearField.GetValue();
- int nMonth = m_MonthField.GetValue();
- int nDay = m_DayField.GetValue();
-
- BOOL res = TRUE;
-
- if (nYear >= 1970 && nYear < 2038 && nMonth >= 1 && nMonth <= 12 && nDay >= 1 && nDay <= 31) {
- CTime ctime(nYear, nMonth, nDay, 0, 0, 0);
-
- res = (ctime.GetYear() == nYear) &&
- (ctime.GetMonth() == nMonth) &&
- (ctime.GetDay() == nDay);
- } else {
- res = FALSE;
- }
-
- if (res) {
- m_nDay = nDay;
- m_nMonth = nMonth;
- m_nYear = nYear;
- } else {
- m_DayField.SetValue(m_nDay);
- m_MonthField.SetValue(m_nMonth);
- m_YearField.SetValue(m_nYear);
- }
- return res;
- }
-
- //================================================================ OnKeyPress
- BOOL CNSDateEdit::OnKeyPress( UINT nKey, UINT nRepCnt, UINT nFlags )
- {
- if (nKey == VK_TAB || nKey == VK_SPACE)
- {
- // Don't move on to the next field/window if the current
- // value is invalid.
- if ( !Validate() )
- {
- MessageBeep( MB_OK );
- m_pFields[m_iCurrentField]->SetSel( 0, -1 );
- return TRUE;
- }
- // Move the focus to the next field or control
- BOOL bShift = GetKeyState( VK_SHIFT ) & 0x8000;
-
- if (bShift) {
- if (m_iCurrentField > 0 || nKey == VK_SPACE)
- m_iCurrentField += 2;
- else
- return FALSE;
- } else {
- if (m_iCurrentField < 2 || nKey == VK_SPACE)
- m_iCurrentField += 1;
- else
- return FALSE;
- }
-
- m_iCurrentField %= 3;
-
- m_pFields[m_iCurrentField]->SetFocus();
-
- return TRUE; // handled
- }
-
- return FALSE; // not handled - let the child continue processing this key
- }
-
- //============================================================= OnMaxText
- void CNSDateEdit::OnMaxText()
- {
- }
-
- //============================================================= OnFocusDay
- void CNSDateEdit::OnFocusDay()
- {
- int nDays = _GetMonthDays(m_nYear, m_nMonth);
-
- for (int i = 0; i < 3; i++) {
- if (m_pFields[i] == &m_DayField)
- m_iCurrentField = i;
- }
- m_wndSpin.SetBuddy(&m_DayField);
- m_wndSpin.SetRange(1, nDays);
- m_wndSpin.SetPos(m_nDay);
- }
-
- //============================================================= OnFocusMonth
- void CNSDateEdit::OnFocusMonth()
- {
- for (int i = 0; i < 3; i++) {
- if (m_pFields[i] == &m_MonthField)
- m_iCurrentField = i;
- }
- m_wndSpin.SetBuddy(&m_MonthField);
- m_wndSpin.SetRange(1, 12);
- m_wndSpin.SetPos(m_nMonth);
- }
-
- //============================================================= OnFocusYear
- void CNSDateEdit::OnFocusYear()
- {
- for (int i = 0; i < 3; i++) {
- if (m_pFields[i] == &m_YearField)
- m_iCurrentField = i;
- }
- m_wndSpin.SetBuddy(&m_YearField);
- m_wndSpin.SetRange(1970, 2037);
- m_wndSpin.SetPos(m_nYear);
- }
-
- //============================================================= OnKillFocusDay
- void CNSDateEdit::OnKillFocusDay()
- {
- if (!Validate()) {
- MessageBeep( MB_OK );
- }
- }
-
- //============================================================= OnKillFocusMonth
- void CNSDateEdit::OnKillFocusMonth()
- {
- if (!Validate()) {
- MessageBeep( MB_OK );
- }
- }
-
- //============================================================= OnKillFocusYear
- void CNSDateEdit::OnKillFocusYear()
- {
- if (!Validate()) {
- MessageBeep( MB_OK );
- }
- }
-
- LRESULT CNSDateEdit::OnRelayEvent(WPARAM wParam, LPARAM lParam)
- {
- LPMSG pMsg = (LPMSG) lParam;
- if (pMsg->message == WM_KEYDOWN) {
- return (LRESULT) OnKeyPress( (UINT) pMsg->wParam, (UINT) LOWORD(pMsg->lParam), (UINT) HIWORD(pMsg->lParam));
- }
- return (LRESULT) FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CNSDateSubedit
-
- //============================================================ CNSDateSubedit
- CNSDateSubedit::CNSDateSubedit()
- {
- }
-
-
- //=========================================================== ~CNSDateSubedit
- CNSDateSubedit::~CNSDateSubedit()
- {
- }
-
- BOOL CNSDateSubedit::PreTranslateMessage( MSG* pMsg )
- {
- if (GetParent()->SendMessage(NSDE_RELAYEVENT, (WPARAM) 0, (LPARAM) pMsg))
- return TRUE;
-
- return CEdit::PreTranslateMessage(pMsg);
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CNSDateSubedit message handlers
-
- BEGIN_MESSAGE_MAP(CNSDateSubedit, CEdit)
- ON_WM_CHAR()
- ON_WM_SETFOCUS()
- END_MESSAGE_MAP()
-
- //==================================================================== OnChar
- void CNSDateSubedit::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags )
- {
- if ( ((nChar >= '0') && (nChar <= '9')) || (nChar == 0x08) ) {
- CEdit::OnChar(nChar, nRepCnt, nFlags);
- } else if (nChar == ' ') {
- MSG msg;
- msg.message = WM_KEYDOWN;
- msg.wParam = (WPARAM) VK_SPACE;
- GetParent()->SendMessage(NSDE_RELAYEVENT, (WPARAM) 0, (LPARAM) &msg);
- } else {
- MessageBeep( MB_OK );
- }
- }
-
- //=============================================================== OnSetFocus
- void CNSDateSubedit::OnSetFocus( CWnd* pOldWnd )
- {
- CEdit::OnSetFocus( pOldWnd );
- SetSel(0,-1);
- }
-
- //================================================================== SetValue
- int CNSDateSubedit::SetValue( int nNewValue )
- {
- char buff[10];
- SetWindowText( itoa( nNewValue, buff, 10 ) );
- return nNewValue;
- }
-
-
- //================================================================== GetValue
- int CNSDateSubedit::GetValue( void )
- {
- char buff[10];
- GetWindowText( buff, 10 );
- if ( strlen( buff ) > 0 )
- return atoi( buff );
- return 0;
- }
-