htmlwin.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,495 行 · 第 1/3 页
CPP
1,495 行
void wxHtmlWindow::OnMouseMove(wxMouseEvent& WXUNUSED(event))
{
m_tmpMouseMoved = true;
}
void wxHtmlWindow::OnMouseDown(wxMouseEvent& event)
{
#if wxUSE_CLIPBOARD
if ( event.LeftDown() && IsSelectionEnabled() )
{
const long TRIPLECLICK_LEN = 200; // 0.2 sec after doubleclick
if ( wxGetLocalTimeMillis() - m_lastDoubleClick <= TRIPLECLICK_LEN )
{
SelectLine(CalcUnscrolledPosition(event.GetPosition()));
(void) CopySelection();
}
else
{
m_makingSelection = true;
if ( m_selection )
{
wxDELETE(m_selection);
Refresh();
}
m_tmpSelFromPos = CalcUnscrolledPosition(event.GetPosition());
m_tmpSelFromCell = NULL;
CaptureMouse();
}
}
#else
wxUnusedVar(event);
#endif // wxUSE_CLIPBOARD
}
void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
{
#if wxUSE_CLIPBOARD
if ( m_makingSelection )
{
ReleaseMouse();
m_makingSelection = false;
// did the user move the mouse far enough from starting point?
if ( CopySelection(Primary) )
{
// we don't want mouse up event that ended selecting to be
// handled as mouse click and e.g. follow hyperlink:
return;
}
}
#endif // wxUSE_CLIPBOARD
SetFocus();
if ( m_Cell )
{
wxPoint pos = CalcUnscrolledPosition(event.GetPosition());
wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
// check is needed because FindCellByPos returns terminal cell and
// containers may have empty borders -- in this case NULL will be
// returned
if ( cell )
OnCellClicked(cell, pos.x, pos.y, event);
}
}
void wxHtmlWindow::OnInternalIdle()
{
wxWindow::OnInternalIdle();
if (m_tmpMouseMoved && (m_Cell != NULL))
{
#ifdef DEBUG_HTML_SELECTION
Refresh();
#endif
int xc, yc, x, y;
wxGetMousePosition(&xc, &yc);
ScreenToClient(&xc, &yc);
CalcUnscrolledPosition(xc, yc, &x, &y);
wxHtmlCell *cell = m_Cell->FindCellByPos(x, y);
// handle selection update:
if ( m_makingSelection )
{
if ( !m_tmpSelFromCell )
m_tmpSelFromCell = m_Cell->FindCellByPos(
m_tmpSelFromPos.x,m_tmpSelFromPos.y);
// NB: a trick - we adjust selFromPos to be upper left or bottom
// right corner of the first cell of the selection depending
// on whether the mouse is moving to the right or to the left.
// This gives us more "natural" behaviour when selecting
// a line (specifically, first cell of the next line is not
// included if you drag selection from left to right over
// entire line):
wxPoint dirFromPos;
if ( !m_tmpSelFromCell )
{
dirFromPos = m_tmpSelFromPos;
}
else
{
dirFromPos = m_tmpSelFromCell->GetAbsPos();
if ( x < m_tmpSelFromPos.x )
{
dirFromPos.x += m_tmpSelFromCell->GetWidth();
dirFromPos.y += m_tmpSelFromCell->GetHeight();
}
}
bool goingDown = dirFromPos.y < y ||
(dirFromPos.y == y && dirFromPos.x < x);
// determine selection span:
if ( /*still*/ !m_tmpSelFromCell )
{
if (goingDown)
{
m_tmpSelFromCell = m_Cell->FindCellByPos(
m_tmpSelFromPos.x,m_tmpSelFromPos.y,
wxHTML_FIND_NEAREST_AFTER);
if (!m_tmpSelFromCell)
m_tmpSelFromCell = m_Cell->GetFirstTerminal();
}
else
{
m_tmpSelFromCell = m_Cell->FindCellByPos(
m_tmpSelFromPos.x,m_tmpSelFromPos.y,
wxHTML_FIND_NEAREST_BEFORE);
if (!m_tmpSelFromCell)
m_tmpSelFromCell = m_Cell->GetLastTerminal();
}
}
wxHtmlCell *selcell = cell;
if (!selcell)
{
if (goingDown)
{
selcell = m_Cell->FindCellByPos(x, y,
wxHTML_FIND_NEAREST_BEFORE);
if (!selcell)
selcell = m_Cell->GetLastTerminal();
}
else
{
selcell = m_Cell->FindCellByPos(x, y,
wxHTML_FIND_NEAREST_AFTER);
if (!selcell)
selcell = m_Cell->GetFirstTerminal();
}
}
// NB: it may *rarely* happen that the code above didn't find one
// of the cells, e.g. if wxHtmlWindow doesn't contain any
// visible cells.
if ( selcell && m_tmpSelFromCell )
{
if ( !m_selection )
{
// start selecting only if mouse movement was big enough
// (otherwise it was meant as mouse click, not selection):
const int PRECISION = 2;
wxPoint diff = m_tmpSelFromPos - wxPoint(x,y);
if (abs(diff.x) > PRECISION || abs(diff.y) > PRECISION)
{
m_selection = new wxHtmlSelection();
}
}
if ( m_selection )
{
if ( m_tmpSelFromCell->IsBefore(selcell) )
{
m_selection->Set(m_tmpSelFromPos, m_tmpSelFromCell,
wxPoint(x,y), selcell); }
else
{
m_selection->Set(wxPoint(x,y), selcell,
m_tmpSelFromPos, m_tmpSelFromCell);
}
m_selection->ClearPrivPos();
Refresh();
}
}
}
// handle cursor and status bar text changes:
if ( cell != m_tmpLastCell )
{
wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL;
wxCursor cur;
if (cell)
cur = cell->GetCursor();
else
cur = *wxSTANDARD_CURSOR;
SetCursor(cur);
if (lnk != m_tmpLastLink)
{
#if wxUSE_STATUSBAR
if (lnk == NULL)
{
if (m_RelatedStatusBar != -1)
m_RelatedFrame->SetStatusText(wxEmptyString,
m_RelatedStatusBar);
}
else
{
if (m_RelatedStatusBar != -1)
m_RelatedFrame->SetStatusText(lnk->GetHref(),
m_RelatedStatusBar);
}
#endif // wxUSE_STATUSBAR
m_tmpLastLink = lnk;
}
m_tmpLastCell = cell;
}
else // mouse moved but stayed in the same cell
{
if ( cell )
OnCellMouseHover(cell, x, y);
}
m_tmpMouseMoved = false;
}
}
#if wxUSE_CLIPBOARD
void wxHtmlWindow::StopAutoScrolling()
{
if ( m_timerAutoScroll )
{
wxDELETE(m_timerAutoScroll);
}
}
void wxHtmlWindow::OnMouseEnter(wxMouseEvent& event)
{
StopAutoScrolling();
event.Skip();
}
void wxHtmlWindow::OnMouseLeave(wxMouseEvent& event)
{
// don't prevent the usual processing of the event from taking place
event.Skip();
// when a captured mouse leave a scrolled window we start generate
// scrolling events to allow, for example, extending selection beyond the
// visible area in some controls
if ( wxWindow::GetCapture() == this )
{
// where is the mouse leaving?
int pos, orient;
wxPoint pt = event.GetPosition();
if ( pt.x < 0 )
{
orient = wxHORIZONTAL;
pos = 0;
}
else if ( pt.y < 0 )
{
orient = wxVERTICAL;
pos = 0;
}
else // we're lower or to the right of the window
{
wxSize size = GetClientSize();
if ( pt.x > size.x )
{
orient = wxHORIZONTAL;
pos = GetVirtualSize().x / wxHTML_SCROLL_STEP;
}
else if ( pt.y > size.y )
{
orient = wxVERTICAL;
pos = GetVirtualSize().y / wxHTML_SCROLL_STEP;
}
else // this should be impossible
{
// but seems to happen sometimes under wxMSW - maybe it's a bug
// there but for now just ignore it
//wxFAIL_MSG( _T("can't understand where has mouse gone") );
return;
}
}
// only start the auto scroll timer if the window can be scrolled in
// this direction
if ( !HasScrollbar(orient) )
return;
delete m_timerAutoScroll;
m_timerAutoScroll = new wxHtmlWinAutoScrollTimer
(
this,
pos == 0 ? wxEVT_SCROLLWIN_LINEUP
: wxEVT_SCROLLWIN_LINEDOWN,
pos,
orient
);
m_timerAutoScroll->Start(50); // FIXME: make configurable
}
}
void wxHtmlWindow::OnKeyUp(wxKeyEvent& event)
{
if ( IsSelectionEnabled() && event.GetKeyCode() == 'C' && event.CmdDown() )
{
(void) CopySelection();
}
}
void wxHtmlWindow::OnCopy(wxCommandEvent& WXUNUSED(event))
{
(void) CopySelection();
}
void wxHtmlWindow::OnDoubleClick(wxMouseEvent& event)
{
// select word under cursor:
if ( IsSelectionEnabled() )
{
SelectWord(CalcUnscrolledPosition(event.GetPosition()));
(void) CopySelection(Primary);
m_lastDoubleClick = wxGetLocalTimeMillis();
}
else
event.Skip();
}
void wxHtmlWindow::SelectWord(const wxPoint& pos)
{
if ( m_Cell )
{
wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
if ( cell )
{
delete m_selection;
m_selection = new wxHtmlSelection();
m_selection->Set(cell, cell);
RefreshRect(wxRect(CalcScrolledPosition(cell->GetAbsPos()),
wxSize(cell->GetWidth(), cell->GetHeight())));
}
}
}
void wxHtmlWindow::SelectLine(const wxPoint& pos)
{
if ( m_Cell )
{
wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
if ( cell )
{
// We use following heuristic to find a "line": let the line be all
// cells in same container as the cell under mouse cursor that are
// neither completely above nor completely bellow the clicked cell
// (i.e. are likely to be words positioned on same line of text).
int y1 = cell->GetAbsPos().y;
int y2 = y1 + cell->GetHeight();
int y;
const wxHtmlCell *c;
const wxHtmlCell *before = NULL;
const wxHtmlCell *after = NULL;
// find last cell of line:
for ( c = cell->GetNext(); c; c = c->GetNext())
{
y = c->GetAbsPos().y;
if ( y + c->GetHeight() > y1 && y < y2 )
after = c;
else
break;
}
if ( !after )
after = cell;
// find first cell of line:
for ( c = cell->GetParent()->GetFirstChild();
c && c != cell; c = c->GetNext())
{
y = c->GetAbsPos().y;
if ( y + c->GetHeight() > y1 && y < y2 )
{
if ( ! before )
before = c;
}
else
before = NULL;
}
if ( !before )
before = cell;
delete m_selection;
m_selection = new wxHtmlSelection();
m_selection->Set(before, after);
Refresh();
}
}
}
void wxHtmlWindow::SelectAll()
{
if ( m_Cell )
{
delete m_selection;
m_selection = new wxHtmlSelection();
m_selection->Set(m_Cell->GetFirstTerminal(), m_Cell->GetLastTerminal());
Refresh();
}
}
#endif // wxUSE_CLIPBOARD
IMPLEMENT_ABSTRACT_CLASS(wxHtmlProcessor,wxObject)
#if wxUSE_EXTENDED_RTTI
IMPLEMENT_DYNAMIC_CLASS_XTI(wxHtmlWindow, wxScrolledWindow,"wx/html/htmlwin.h")
wxBEGIN_PROPERTIES_TABLE(wxHtmlWindow)
/*
TODO PROPERTIES
style , wxHW_SCROLLBAR_AUTO
borders , (dimension)
url , string
htmlcode , string
*/
wxEND_PROPERTIES_TABLE()
wxBEGIN_HANDLERS_TABLE(wxHtmlWindow)
wxEND_HANDLERS_TABLE()
wxCONSTRUCTOR_5( wxHtmlWindow , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
#else
IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
#endif
BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
EVT_SIZE(wxHtmlWindow::OnSize)
EVT_LEFT_DOWN(wxHtmlWindow::OnMouseDown)
EVT_LEFT_UP(wxHtmlWindow::OnMouseUp)
EVT_RIGHT_UP(wxHtmlWindow::OnMouseUp)
EVT_MOTION(wxHtmlWindow::OnMouseMove)
EVT_ERASE_BACKGROUND(wxHtmlWindow::OnEraseBackground)
EVT_PAINT(wxHtmlWindow::OnPaint)
#if wxUSE_CLIPBOARD
EVT_LEFT_DCLICK(wxHtmlWindow::OnDoubleClick)
EVT_ENTER_WINDOW(wxHtmlWindow::OnMouseEnter)
EVT_LEAVE_WINDOW(wxHtmlWindow::OnMouseLeave)
EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
#endif // wxUSE_CLIPBOARD
END_EVENT_TABLE()
// A module to allow initialization/cleanup
// without calling these functions from app.cpp or from
// the user's application.
class wxHtmlWinModule: public wxModule
{
DECLARE_DYNAMIC_CLASS(wxHtmlWinModule)
public:
wxHtmlWinModule() : wxModule() {}
bool OnInit() { return true; }
void OnExit() { wxHtmlWindow::CleanUpStatics(); }
};
IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinModule, wxModule)
// This hack forces the linker to always link in m_* files
// (wxHTML doesn't work without handlers from these files)
#include "wx/html/forcelnk.h"
FORCE_WXHTML_MODULES()
#endif // wxUSE_HTML
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?