⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 custctrl.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            )
    {
    // character?
    #if wxUSE_UNICODE
    # if wxMINOR_VERSION < 5 || ( wxMINOR_VERSION == 5 && wxRELEASE_NUMBER < 3 )
        // The old way with unicode.
        //wxChar c = event.m_uniChar didn't work.
        wxChar c = (wxChar) keycode;
    # else
        // The new way (2.5.3+).
        wxChar c = event.GetUnicodeKey();
    # endif
    #else
        wxChar c = (wxChar) keycode;
    #endif

        DeleteSelection();

        m_text.insert ( m_position, 1, c );
        
        ctrl->SetInsertionPoint ( m_position + 1, m_position );
        
        ctrl->Draw();

        manager->AddEvent (ctrl,wxEVT_COMMAND_TEXT_UPDATED);
    }
    else
    {
        // Clipboard operations
        int cb_op = 100; // 100 = invalid

        // Cut:   Ctrl-X and Shift-Del
        // Copy:  Ctrl-C and ???
        // Paste: Ctrl-V and Shift-Ins

        if ( event.ControlDown() )
        {
            if ( keycode == wxT('X') ) cb_op = 1;
            else if ( keycode == wxT('C') ) cb_op = 2;
            else if ( keycode == wxT('V') ) cb_op = 3;
        }
        else if ( event.ShiftDown() )
        {
            if ( keycode == WXK_DELETE ) cb_op = 1;
            //else if ( keycode == wxT('C') ) cb_op = 2;
            else if ( keycode == WXK_INSERT ) cb_op = 3;
        }

        // Clipboard operations
        if ( cb_op < 3 )
        {
        // Cut and Copy
            if ( m_selStart >= 0 && wxTheClipboard->Open() )
            {
                wxTextDataObject* obj = new wxTextDataObject(
                    m_text.Mid(m_selStart,m_selEnd-m_selStart)
                    );
                //wxLogDebug ( wxT("data_object = 0x%X"), (size_t)obj );
                wxTheClipboard->AddData( obj );

                // Cut-only Portion
                if ( cb_op == 1 )
                {
                    DeleteSelection();

                    ctrl->SetInsertionPoint ( m_position );

                    ctrl->Draw();

                    manager->AddEvent (ctrl,wxEVT_COMMAND_TEXT_UPDATED);
                }

                wxTheClipboard->Close();

                wxTheClipboard->Flush();

                //delete obj;
            }
        }
        else if ( cb_op == 3 )
        {
        // Paste

            if ( wxTheClipboard->Open() )
            {
                if (wxTheClipboard->IsSupported( wxDF_TEXT ))
                {
                    wxTextDataObject data;
                    wxTheClipboard->GetData( data );
                    wxString text = data.GetText();

                    DeleteSelection();

                    m_text.insert ( m_position, text );

                    ctrl->SetInsertionPoint ( m_position + text.length(), m_position + text.length() - 1 );

                    ctrl->Draw();

                    manager->AddEvent (ctrl,wxEVT_COMMAND_TEXT_UPDATED);
                }  
                wxTheClipboard->Close();
            }
        }
        else
            return FALSE;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

bool wxCustomTextCtrlHandler::OnMouseEvent ( wxMouseEvent& event )
{
    wxCCustomTextCtrl* ctrl = (wxCCustomTextCtrl*)m_control;
    int x = event.GetPosition().x;

    if ( event.GetEventType() == wxEVT_MOTION )
    {
        //wxLogDebug ( wxT("wxCustomTextCtrlHandler::OnMouseEvent(wxEVT_MOTION)") );

        if ( event.Dragging() && m_control->GetManager()->IsDragging () )
        {
            // Fix position;
            if ( x < wxCC_TEXTCTRL_XSPACING )
                x = wxCC_TEXTCTRL_XSPACING;
            else if ( x >= (m_rect.width-wxCC_TEXTCTRL_XSPACING) )
                x = (m_rect.width-1-wxCC_TEXTCTRL_XSPACING);

            int hitpos;

            if ( HitTest(x,&hitpos) >= wxTE_HT_ON_TEXT /*&& hitpos != -1*/ )
            {
                int ns1, ns2;
                if ( hitpos < m_itemButDown )
                {
                    ns1 = hitpos;
                    ns2 = m_itemButDown;
                }
                else if ( hitpos > m_itemButDown )
                {
                    ns1 = m_itemButDown;
                    ns2 = hitpos;
                }
                else
                {
                    ns1 = -1;
                    ns2 = m_selEnd;
                }

                if ( m_selStart != ns1 || m_selEnd != ns2 )
                {
                    m_selStart = ns1;
                    m_selEnd = ns2;
                    ctrl->Draw();
                    ctrl->SetInsertionPoint ( hitpos );
                }
            }
        }
    }
    else if ( event.GetEventType() == wxEVT_LEFT_DOWN 
#if !wxPG_TEXTCTRL_DOUBLE_CLICK_MODE
              || event.GetEventType() == wxEVT_LEFT_DCLICK
#endif
            )
    {
        //wxLogDebug ( wxT("wxCustomTextCtrlHandler::OnMouseEvent(wxEVT_LEFT_DOWN)") );
        int hitpos;

        if ( HitTest(x,&hitpos) >= wxTE_HT_ON_TEXT )
        {
            ctrl->SetInsertionPoint ( hitpos );

            m_itemButDown = hitpos;

            // Clear selection?
            if ( m_selStart != -1 )
            {
                m_selStart = -1;
                ctrl->Draw ();
            }
        }

    }
#if wxPG_TEXTCTRL_DOUBLE_CLICK_MODE
    else if ( event.GetEventType() == wxEVT_LEFT_DCLICK )
    {
        // Select double-clicked word.

        int hitpos;

        if ( HitTest(x,&hitpos) >= wxTE_HT_ON_TEXT )
        {
            // hitpos = first character that is not counted.

            int textlen = m_text.length();

            // Find start pos
            int startpos = hitpos-1;
            if ( startpos >= 0 )
            {
                const wxChar* p = &m_text.c_str()[startpos];
                while ( startpos >= 0 && *p > wxT(' ') )
                {
                    p--;
                    startpos--;
                }
                startpos++;
            }

            // Find end pos
            int endpos = hitpos-1;
            if ( endpos >= 0 )
            {
                const wxChar* p = &m_text.c_str()[endpos];
                while ( endpos < textlen && *p > wxT(' ') )
                {
                    p++;
                    endpos++;
                }
            #if wxPG_TEXTCTRL_DOUBLE_CLICK_MODE == 2
                while ( endpos < textlen && *p <= wxT(' ') )
                {
                    p++;
                    endpos++;
                }
            #endif
            }

            if ( endpos > startpos )
            {
                m_selStart = startpos;
                m_selEnd = endpos;
            }
            else
            {
                m_selStart = -1;
                endpos = hitpos;
            }

            ctrl->Draw();
            ctrl->SetInsertionPoint ( endpos );
        }
    }
#endif
    return FALSE;
}

// -----------------------------------------------------------------------

void wxCustomTextCtrlHandler::SetValue ( const wxString& value )
{
    m_scrollPosition = 0;
    m_position = 0;
    m_selStart = -1;
    m_text = value;
    m_flags |= wxCC_FL_MODIFIED;
}

// -----------------------------------------------------------------------

void wxCustomTextCtrlHandler::Draw ( wxDC& dc, const wxRect& rect )
{
#if __INTENSE_DEBUGGING__
    wxLogDebug ( wxT("wxCustomTextCtrlHandler::Draw()") );
#endif
    wxCustomControl* ctrl = m_control;
    //const wxRect& rect = m_rect;

    wxASSERT ( ctrl->m_pFont != NULL );

    wxCustomControlManager* manager = ctrl->m_manager;

    wxWindow* parent = manager->m_parent;

    //wxWindow* parent = m_parent;
    wxString* str = &m_text;
    //wxString& tempstr = manager->m_tempStr1;
    wxString tempstr;

    wxRect write_rect(rect.x+wxCC_TEXTCTRL_XSPACING,
                      rect.y,
                      rect.width-(wxCC_TEXTCTRL_XSPACING*2),
                      rect.height);

    //wxLogDebug ( wxT("CC: DRAW ( x = %i, y = %i, text = %s )"), (int)rect.x, (int)rect.y,
    //    str->c_str() );

    manager->HideCaretBalanced();

    dc.SetBrush ( manager->GetWindowColour() );
    dc.SetPen ( manager->GetWindowColour() );
    
    dc.DrawRectangle ( rect );

    // get font metrics
    dc.SetFont ( *ctrl->m_pFont );
    dc.SetTextForeground ( manager->GetWindowTextColour() );

    //int fw = dc.GetCharWidth() + 1;
    int fh = dc.GetCharHeight();

    if ( fh < rect.height )
    {
        write_rect.y += (rect.height - fh) / 2;
        write_rect.height = fh;
    }

    // determine number of characters to write.
    unsigned int scrollpos = m_scrollPosition;

    int hitpos;
    if ( HitTest(rect.width-wxCC_TEXTCTRL_XSPACING/*-3+2*/,&hitpos) < wxTE_HT_ON_TEXT )
    {
        manager->ShowCaretBalanced();
        return;
    }
    /*
    int res = HitTest ( wxPoint(rect.width-wxCC_TEXTCTRL_XSPACING-3+2,wxCC_TEXTCTRL_YSPACING+1) );
    if ( res < 1 )
    {
        manager->ShowCaretBalanced();
        return;
    }
    */

    unsigned int write_end = (unsigned int)hitpos;

#ifdef __WXDEBUG__
    if ( write_end < scrollpos)
    {
        wxLogDebug ( wxT("ERROR: write_end (%u) should be more than scrollpos (%u) "),
            write_end, scrollpos );
        wxASSERT ( write_end >= scrollpos );
        manager->ShowCaretBalanced();
        return;
    }
#endif

    unsigned int charcount = write_end - scrollpos;

    //wxLogDebug ( wxT("    (%i, %i, %i, %i)"), rect.x, rect.y, rect.width, rect.height );

    if ( m_selStart < 0 ||
         (unsigned int)m_selStart >= write_end ||
         (unsigned int)m_selEnd <= scrollpos 
       )
    {

        // No selection to be drawn
        tempstr = str->Mid(scrollpos,charcount);
        dc.DrawText ( tempstr, write_rect.x, write_rect.y );
    }
    else
    {
        // Selection has to be drawn

        int w1 = 0, w2 = 0;
        unsigned int selstart = (unsigned int) m_selStart;
        if ( selstart < scrollpos ) selstart = scrollpos;
        unsigned int selend = (unsigned int) m_selEnd;
        if ( selend > write_end ) selend = write_end;

        // unselected portion 1

        if ( selstart > scrollpos )
        {
            tempstr = str->Mid(scrollpos, selstart-scrollpos);
            parent->GetTextExtent (tempstr,&w1,&fh,NULL,NULL,ctrl->m_pFont);
            dc.DrawText ( tempstr, write_rect.x, write_rect.y );
        }

        // selected portion

        if ( selend > scrollpos )
        {
            tempstr = str->Mid(selstart,selend-selstart);
            parent->GetTextExtent (tempstr,&w2,&fh,NULL,NULL,ctrl->m_pFont);

            dc.SetBrush ( manager->GetSelectionColour() );
            dc.SetPen ( manager->GetSelectionColour() );
            dc.DrawRectangle ( write_rect.x+w1, write_rect.y, w2, write_rect.height );
            dc.SetTextForeground ( manager->GetSelectionTextColour() );

            dc.DrawText ( tempstr, write_rect.x+w1, write_rect.y );
        }

        // unselected portion 2

        if ( selend < write_end )
        {
            dc.SetTextForeground ( manager->GetWindowTextColour() );
            tempstr = str->Mid(selend, write_end-selend);
            dc.DrawText ( tempstr, write_rect.x+w1+w2, write_rect.y );
        }
    }

#if __INTENSE_DEBUGGING__
    wxLogDebug ( wxT("  ends...") );
#endif

    manager->ShowCaretBalanced();
}

// -----------------------------------------------------------------------

// should be faster than creating new string for a sub-string (as with Mid)
inline void wxstring_copy ( wxString& dst, wxString& src, unsigned int pos, unsigned int len )
{
    wxChar* ptr = (wxChar*)&src.GetWritableChar(pos);
    wxChar cb = ptr[len];
    ptr[len] = 0; // terminate
    dst = ptr;
    ptr[len] = cb; // revert to original
}

// -----------------------------------------------------------------------

// used by HitTest
/*
int wxCustomTextCtrlHandler::UpdateExtentCache ( wxString& tempstr, size_t index )
{
    int tw, th;
    wxArrayInt& arrext = m_arrExtents;
    unsigned int startpos = m_scrollPosition;
    if ( index >= arrext.GetCount() ) arrext.SetCount(index+1,-1);
    wxWindow* parent = m_control->GetParent();
    wxstring_copy ( tempstr, m_text, startpos, index );
    parent->GetTextExtent ( tempstr, &tw, &th, NULL, NULL, &m_control->GetFont() );
    
    //wxLogDebug (wxT("wxCustomTextCtrlHandler::UpdateExtentCache(%i)"),(int)index);

    arrext.Item(index) = tw;
    return tw;
}

#define wxCTC_HITTEST_GETEXTENT(INDEX) \
        if ( INDEX < arrext.GetCount() && arrext.Item(INDEX) >= 0 ) \
            tw = arrext.Item(INDEX); \
        else \
            tw = UpdateExtentCache(tempstr,INDEX); \

*/

#define wxCTC_HITTEST_GETEXTENT(INDEX) \
    wxstring_copy ( tempstr, m_text, m_scrollPosition, INDEX ); \
    dc.GetTextExtent ( tempstr, &tw, NULL );

//parent->GetTextExtent ( tempstr, &tw, &th, NULL, NULL, &m_control->GetFont() );

// -----------------------------------------------------------------------

    // Linear search
    /*
    i = 0;
    lo = hi;
    int prev_tw = -100;

    while ( i < hi )
   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -