#include "stdafx.h"
#include "CellEditingII.h"
#include "CellEditingIIDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCellEditingDlg dialog

CCellEditingDlg::CCellEditingDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CCellEditingDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CCellEditingDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCellEditingDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CCellEditingDlg)
    DDX_Control(pDX, IDC_TEXT2, m_Title2);
    DDX_Control(pDX, IDC_TEXT1, m_Title1);
    DDX_Control(pDX, IDC_SFTTREE1, m_Tree1);
    DDX_Control(pDX, IDC_SFTMASKAMOUNT, m_Amount);
    DDX_Control(pDX, IDC_SFTMASKCALENDAR, m_Date);
    DDX_Control(pDX, IDC_SFTBOX1, m_SftBox1);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CCellEditingDlg, CDialog)
    //{{AFX_MSG_MAP(CCellEditingDlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCellEditingDlg message handlers

BOOL CCellEditingDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    m_vTree = m_Tree1.GetControlUnknown();
    ASSERT(m_vTree != NULL);
    m_vAmount = m_Amount.GetControlUnknown();
    ASSERT(m_vAmount != NULL);
    m_vDate = m_Date.GetControlUnknown();
    ASSERT(m_vDate != NULL);
    m_vCombo = m_SftBox1.GetControlUnknown();
    ASSERT(m_vDate != NULL);

    m_Title1.SetWindowText(_T("In this example, the first column uses a SftMask/OCX Masked Edit control ")
      _T("to enter an amount.  Try entering a new amount, then type + or - to access the built-in ")
      _T("popup calculator.\n\n")
      _T("The second column uses a SftBox/OCX Combo Box control.\n\n")
      _T("The last column again uses a SftMask/OCX Masked Edit control to enter a date.  Click on the ")
      _T("drop down button to access the popup calendar."));

    m_Title2.SetWindowText(_T(""));

    long ItemIndex;

    DATE Dt = (DATE) COleDateTime::GetCurrentTime();

    ItemIndex = m_vTree->Items->Add(_T("Edit cells\nusing SftMask/OCX:"));
    m_vTree->Item[ItemIndex]->EditIgnore = VARIANT_true;
    m_vTree->Cell[ItemIndex][1]->Text = _T("\nusing SftBox/OCX:");
    m_vTree->Cell[ItemIndex][2]->Text = _T("and again\nusing SftMask/OCX:");
    
    ItemIndex = m_vTree->Items->Add(_T("5.33"));
    m_vTree->Cell[ItemIndex][0]->TextHAlign = halignSftTreeDefaultRight;
    m_vTree->Cell[ItemIndex][1]->Text = _T("Option 1");
    BSTR str;
    str = SysAllocString(L"short");
    m_vDate->Calendar->FormatDate(Dt-1, &str);
    m_vTree->Cell[ItemIndex][2]->Text = str;
    SysFreeString(str);
    m_vTree->Cell[ItemIndex][2]->DataTag = Dt - 1;
    
    ItemIndex = m_vTree->Items->Add(_T("122.33"));
    m_vTree->Cell[ItemIndex][0]->TextHAlign = halignSftTreeDefaultRight;
    m_vTree->Cell[ItemIndex][1]->Text = _T("Option 2");
    str = SysAllocString(L"short");
    m_vDate->Calendar->FormatDate(Dt, &str);
    m_vTree->Cell[ItemIndex][2]->Text = str;
    SysFreeString(str);
    m_vTree->Cell[ItemIndex][2]->DataTag = Dt;
    
    ItemIndex = m_vTree->Items->Add(_T("66.05"));
    m_vTree->Cell[ItemIndex][0]->TextHAlign = halignSftTreeDefaultRight;
    m_vTree->Cell[ItemIndex][1]->Text = _T("Option 3");
    str = SysAllocString(L"short");
    m_vDate->Calendar->FormatDate(Dt+1, &str);
    m_vTree->Cell[ItemIndex][2]->Text = str;
    SysFreeString(str);
    m_vTree->Cell[ItemIndex][2]->DataTag = Dt+1;

    m_vTree->ColumnsObj->MakeOptimal();
    m_vTree->RowHeaders->MakeOptimal();
    m_vTree->Items->RecalcHorizontalExtent();

    m_vTree->Item[0]->Selected = VARIANT_true;

    return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CCellEditingDlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CCellEditingDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

void CCellEditingDlg::OnItemClickSftTree1(long ItemIndex, short ColIndex, short AreaType, short Button, short Shift) 
{
    // User clicked on a cell
    if (AreaType == constSftTreeCellText)
        m_vTree->Cell[ItemIndex][ColIndex]->Edit(NULL, _variant_t(0L));
}

void CCellEditingDlg::OnEditAllowedSftTree1(long ItemIndex, short ColIndex, BOOL FAR* Allowed) 
{
    // Last chance to suppress cell editing for a cell
    //if (ItemIndex == 1 && ColIndex == 1)
    //    *Allowed = VARIANT_FALSE;
}

void CCellEditingDlg::OnEditInitializingSftTree1(long FAR* Window, VARIANT FAR* vData, long EditIndex, short EditCol, long FAR* LeftPix, long FAR* TopPix, long FAR* WidthPix, long FAR* HeightPix) 
{
    HWND hWindow;
    
    // Choose a control based on current column being edited
    if (EditCol == 0)
        hWindow = m_Amount;
    else if (EditCol == 1)
        hWindow = m_SftBox1;
    else
        hWindow = m_Date;

    CRect rect;
    ::GetWindowRect(hWindow, &rect);
    
    // LeftPix/TopPix/WidthPix/HeightPix describes the current cell area
    // we need to return the position and size needed for editing.
    // In this example, we use the height of the control on the form
    // and center it over the cell.
    
    *TopPix = *TopPix + (*HeightPix - rect.Height()) / 2;
    *HeightPix = rect.Height();
    
    // Set the text in the control used for cell editing and
    // set other control-specific properties
    if (hWindow == m_Amount) {
        m_vAmount->Text = m_vTree->Cell[EditIndex][EditCol]->Text;
        m_vAmount->SelStart = 0;
        m_vAmount->SelLength = 999;
    } else if (hWindow == m_Date) {
        DATE Dt = (DATE) m_vTree->Cell[EditIndex][EditCol]->DataTag;
        m_vDate->Contents->DateTime = Dt;
    } else {
        m_vCombo->Items->Clear();
        long ItemIndex = m_vCombo->Items->Add("Option 1");
        m_vCombo->Cell[ItemIndex][1]->Text = "Description for option 1";
        ItemIndex = m_vCombo->Items->Add("Option 2");
        m_vCombo->Cell[ItemIndex][1]->Text = "Description for option 2";
        ItemIndex = m_vCombo->Items->Add("Option 3");
        m_vCombo->Cell[ItemIndex][1]->Text = "Description for option 3";
        
        _bstr_t str = m_vTree->Cell[EditIndex][EditCol]->Text;
        if (m_vCombo->Items->Find(str, 0, 0, VARIANT_FALSE, VARIANT_true, VARIANT_FALSE) < 0) {
            ItemIndex = m_vCombo->Items->Add(str);
            m_vCombo->Cell[ItemIndex][1]->Text = _bstr_t("Description for ") + str;
        }
        m_vCombo->Columns->MakeOptimal(0);
        m_vCombo->RecalcHorizontalExtent(0);
        m_vCombo->Edit->Text = str;
    }
    
    // Return the control's window handle
    *Window = (OLE_HANDLE) hWindow;

    // Define navigation keys
    // VK_TAB
    m_vTree->CellEditIntercept(VK_TAB, (SftTreeCellEditInterceptStyleConstants)(cellEditInterceptSftTreeChar | cellEditInterceptSftTreeControlChar | cellEditInterceptSftTreeShiftChar));
    // VK_RETURN
    m_vTree->CellEditIntercept(VK_RETURN, (SftTreeCellEditInterceptStyleConstants)(cellEditInterceptSftTreeChar | cellEditInterceptSftTreeControlChar | cellEditInterceptSftTreeShiftChar));
    // VK_HOME
    m_vTree->CellEditIntercept(VK_HOME, cellEditInterceptSftTreeControlChar);
    // VK_END
    m_vTree->CellEditIntercept(VK_END, cellEditInterceptSftTreeControlChar);
    if (hWindow == m_Amount) {
        // We want these keys just for the amount edit control.
        // VK_UP
        m_vTree->CellEditIntercept(VK_UP,(SftTreeCellEditInterceptStyleConstants)(cellEditInterceptSftTreeChar | cellEditInterceptSftTreeControlChar | cellEditInterceptSftTreeShiftChar));
        // VK_DOWN
        m_vTree->CellEditIntercept(VK_DOWN, (SftTreeCellEditInterceptStyleConstants)(cellEditInterceptSftTreeChar | cellEditInterceptSftTreeControlChar | cellEditInterceptSftTreeShiftChar));
    }
    
}

void CCellEditingDlg::OnEditInitializedSftTree1(long Window, const VARIANT FAR& vData, long EditIndex, short EditCol, long ParentWindow, long LeftPix, long TopPix, long WidthPix, long HeightPix, BOOL FAR* Positioned) 
{
    // We position the control (ActiveX controls must be positioned using the EditInitialized event)
    *Positioned = VARIANT_true;
    
    if ((HWND)Window == m_Amount) {
        m_Amount.MoveWindow(LeftPix, TopPix, WidthPix, HeightPix, FALSE);
        m_Amount.EnableWindow();
        m_Amount.ShowWindow(SW_SHOWNORMAL);
        m_Amount.SetFocus();
    } else if ((HWND)Window == m_Date) {
        m_Date.MoveWindow(LeftPix, TopPix, WidthPix, HeightPix, FALSE);
        m_Date.EnableWindow();
        m_Date.ShowWindow(SW_SHOWNORMAL);
        m_Date.SetFocus();
    } else {
        m_SftBox1.MoveWindow(LeftPix, TopPix, WidthPix, HeightPix, FALSE);
        m_SftBox1.EnableWindow(TRUE);
        m_SftBox1.ShowWindow(SW_SHOWNORMAL);
        m_vCombo->Edit->SetSelection(0, -1);
        m_vCombo->DropDown->Dropped = VARIANT_true;
    }
}

void CCellEditingDlg::OnEditNavigatingSftTree1(long Key, short Shift, long ItemIndex, short ColIndex) 
{
    // Process key pressed
    m_vTree->EditNavigate(Key, Shift);
}

void CCellEditingDlg::OnEditValidateSftTree1(long Window, const VARIANT FAR& vData, long EditIndex, short EditCol, BOOL FAR* InputValid) 
{
    // Validate the new cell contents
    _bstr_t str;
    if ((HWND)Window == m_Amount) {
        if (!m_vAmount->Contents->Valid) {
            // could validate
        }
        str = m_vAmount->TextDisplay;
    } else if ((HWND)Window == m_Date) {
        if (!m_vDate->Contents->Valid) {
            AfxMessageBox(_T("Please enter a valid date."));
            *InputValid = VARIANT_FALSE;
            return;
        }
        str = m_vDate->TextDisplay;
    } else
        str = m_vCombo->Edit->Text;

    if (str.length() <= 0) {
        AfxMessageBox(_T("Just to demonstrate data input validation, this example rejects empty cells.  Please enter some data."));
        *InputValid = VARIANT_FALSE;
    }
}

void CCellEditingDlg::OnEditEndingSftTree1(long Window, const VARIANT FAR& vData, long EditIndex, short EditCol, BOOL SaveInput) 
{
    // Save the new cell contents
    if ((HWND)Window == m_Amount) {
        m_Amount.ShowWindow(FALSE);
        m_Amount.EnableWindow(FALSE);
        if (SaveInput)
            m_vTree->Cell[EditIndex][EditCol]->Text = m_vAmount->TextDisplay;
    } else if ((HWND)Window == m_Date) {
        m_Date.ShowWindow(FALSE);
        m_Date.EnableWindow(FALSE);
        if (SaveInput) {
            m_vTree->Cell[EditIndex][EditCol]->Text = m_vDate->TextDisplay;
            m_vTree->Cell[EditIndex][EditCol]->DataTag = m_vDate->Contents->DateTime;
        }
    } else {
        m_SftBox1.ShowWindow(FALSE);
        m_SftBox1.EnableWindow(FALSE);
        if (SaveInput)
            m_vTree->Cell[EditIndex][EditCol]->Text = m_vCombo->Edit->Text;
    }
}

void CCellEditingDlg::OnToolTipVScrollSftTree1(BSTR FAR* Text, long ItemIndex, short ColIndex) 
{

    _bstr_t s(*Text, false);
    CString str;
    str.Format(_T("Item %ld = %s"), ItemIndex, (LPCTSTR)s);
    *Text = str.AllocSysString();
}

void CCellEditingDlg::OnUpDownPressSftMaskAmount(BOOL Up, long FieldStart, long FieldEnd, long Counter, BSTR FAR* Field) 
{
    double Incr;

    if (Counter == 0 || Counter > 5) {
        wchar_t* endchar;
        double Val = wcstod(*Field, &endchar);

        Incr = 0.01;
        if (Counter > 14) Incr = 0.1;
        if (Counter > 23) Incr = 1.0;
        if (Counter > 52) Incr = 10.0;

        if (Up)
            Val += Incr;
        else
            Val -= Incr;
        if (Val > 99999999.99) Val = 99999999.99;
        if (Val < -99999999.99) Val = -99999999.99;

        wchar_t szBuffer[100];
        swprintf(szBuffer, L"%#8.2f", Val);

        SysFreeString(*Field);
        *Field = SysAllocString(szBuffer);
    }
}

BEGIN_EVENTSINK_MAP(CCellEditingDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CCellEditingDlg)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 4 /* ItemClick */, OnItemClickSftTree1, VTS_I4 VTS_I2 VTS_I2 VTS_I2 VTS_I2)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 44 /* EditAllowed */, OnEditAllowedSftTree1, VTS_I4 VTS_I2 VTS_PBOOL)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 38 /* EditInitializing */, OnEditInitializingSftTree1, VTS_PI4 VTS_PVARIANT VTS_I4 VTS_I2 VTS_PI4 VTS_PI4 VTS_PI4 VTS_PI4)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 39 /* EditInitialized */, OnEditInitializedSftTree1, VTS_I4 VTS_VARIANT VTS_I4 VTS_I2 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_PBOOL)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 43 /* EditNavigating */, OnEditNavigatingSftTree1, VTS_I4 VTS_I2 VTS_I4 VTS_I2)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 37 /* EditValidate */, OnEditValidateSftTree1, VTS_I4 VTS_VARIANT VTS_I4 VTS_I2 VTS_PBOOL)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 36 /* EditEnding */, OnEditEndingSftTree1, VTS_I4 VTS_VARIANT VTS_I4 VTS_I2 VTS_BOOL)
    ON_EVENT(CCellEditingDlg, IDC_SFTTREE1, 28 /* ToolTipVScroll */, OnToolTipVScrollSftTree1, VTS_PBSTR VTS_I4 VTS_I2)
    ON_EVENT(CCellEditingDlg, IDC_SFTMASKAMOUNT, 29 /* UpDownPress */, OnUpDownPressSftMaskAmount, VTS_BOOL VTS_I4 VTS_I4 VTS_I4 VTS_PBSTR)
    //}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()