📄 custctrl.cpp
字号:
)
{
// 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 + -