htmlwin.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,495 行 · 第 1/3 页

CPP
1,495
字号
    }
    else
    {
        int y;

        for (y = 0; c != NULL; c = c->GetParent()) y += c->GetPosY();
        Scroll(-1, y / wxHTML_SCROLL_STEP);
        m_OpenedAnchor = anchor;
        return true;
    }
}


void wxHtmlWindow::OnSetTitle(const wxString& title)
{
    if (m_RelatedFrame)
    {
        wxString tit;
        tit.Printf(m_TitleFormat, title.c_str());
        m_RelatedFrame->SetTitle(tit);
    }
    m_OpenedPageTitle = title;
}





void wxHtmlWindow::CreateLayout()
{
    int ClientWidth, ClientHeight;

    if (!m_Cell) return;

    if (m_Style & wxHW_SCROLLBAR_NEVER)
    {
        SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // always off
        GetClientSize(&ClientWidth, &ClientHeight);
        m_Cell->Layout(ClientWidth);
    }

    else {
        GetClientSize(&ClientWidth, &ClientHeight);
        m_Cell->Layout(ClientWidth);
        if (ClientHeight < m_Cell->GetHeight() + GetCharHeight())
        {
            SetScrollbars(
                  wxHTML_SCROLL_STEP, wxHTML_SCROLL_STEP,
                  m_Cell->GetWidth() / wxHTML_SCROLL_STEP,
                  (m_Cell->GetHeight() + GetCharHeight()) / wxHTML_SCROLL_STEP
                  /*cheat: top-level frag is always container*/);
        }
        else /* we fit into window, no need for scrollbars */
        {
            SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // disable...
            GetClientSize(&ClientWidth, &ClientHeight);
            m_Cell->Layout(ClientWidth); // ...and relayout
        }
    }
}



void wxHtmlWindow::ReadCustomization(wxConfigBase *cfg, wxString path)
{
    wxString oldpath;
    wxString tmp;
    int p_fontsizes[7];
    wxString p_fff, p_ffn;

    if (path != wxEmptyString)
    {
        oldpath = cfg->GetPath();
        cfg->SetPath(path);
    }

    m_Borders = cfg->Read(wxT("wxHtmlWindow/Borders"), m_Borders);
    p_fff = cfg->Read(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
    p_ffn = cfg->Read(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
    for (int i = 0; i < 7; i++)
    {
        tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
        p_fontsizes[i] = cfg->Read(tmp, m_Parser->m_FontsSizes[i]);
    }
    SetFonts(p_ffn, p_fff, p_fontsizes);

    if (path != wxEmptyString)
        cfg->SetPath(oldpath);
}



void wxHtmlWindow::WriteCustomization(wxConfigBase *cfg, wxString path)
{
    wxString oldpath;
    wxString tmp;

    if (path != wxEmptyString)
    {
        oldpath = cfg->GetPath();
        cfg->SetPath(path);
    }

    cfg->Write(wxT("wxHtmlWindow/Borders"), (long) m_Borders);
    cfg->Write(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
    cfg->Write(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
    for (int i = 0; i < 7; i++)
    {
        tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
        cfg->Write(tmp, (long) m_Parser->m_FontsSizes[i]);
    }

    if (path != wxEmptyString)
        cfg->SetPath(oldpath);
}



bool wxHtmlWindow::HistoryBack()
{
    wxString a, l;

    if (m_HistoryPos < 1) return false;

    // store scroll position into history item:
    int x, y;
    GetViewStart(&x, &y);
    (*m_History)[m_HistoryPos].SetPos(y);

    // go to previous position:
    m_HistoryPos--;

    l = (*m_History)[m_HistoryPos].GetPage();
    a = (*m_History)[m_HistoryPos].GetAnchor();
    m_HistoryOn = false;
    m_tmpCanDrawLocks++;
    if (a == wxEmptyString) LoadPage(l);
    else LoadPage(l + wxT("#") + a);
    m_HistoryOn = true;
    m_tmpCanDrawLocks--;
    Scroll(0, (*m_History)[m_HistoryPos].GetPos());
    Refresh();
    return true;
}

bool wxHtmlWindow::HistoryCanBack()
{
    if (m_HistoryPos < 1) return false;
    return true ;
}


bool wxHtmlWindow::HistoryForward()
{
    wxString a, l;

    if (m_HistoryPos == -1) return false;
    if (m_HistoryPos >= (int)m_History->GetCount() - 1)return false;

    m_OpenedPage = wxEmptyString; // this will disable adding new entry into history in LoadPage()

    m_HistoryPos++;
    l = (*m_History)[m_HistoryPos].GetPage();
    a = (*m_History)[m_HistoryPos].GetAnchor();
    m_HistoryOn = false;
    m_tmpCanDrawLocks++;
    if (a == wxEmptyString) LoadPage(l);
    else LoadPage(l + wxT("#") + a);
    m_HistoryOn = true;
    m_tmpCanDrawLocks--;
    Scroll(0, (*m_History)[m_HistoryPos].GetPos());
    Refresh();
    return true;
}

bool wxHtmlWindow::HistoryCanForward()
{
    if (m_HistoryPos == -1) return false;
    if (m_HistoryPos >= (int)m_History->GetCount() - 1)return false;
    return true ;
}


void wxHtmlWindow::HistoryClear()
{
    m_History->Empty();
    m_HistoryPos = -1;
}

void wxHtmlWindow::AddProcessor(wxHtmlProcessor *processor)
{
    if (!m_Processors)
    {
        m_Processors = new wxHtmlProcessorList;
    }
    wxHtmlProcessorList::compatibility_iterator node;

    for (node = m_Processors->GetFirst(); node; node = node->GetNext())
    {
        if (processor->GetPriority() > node->GetData()->GetPriority())
        {
            m_Processors->Insert(node, processor);
            return;
        }
    }
    m_Processors->Append(processor);
}

/*static */ void wxHtmlWindow::AddGlobalProcessor(wxHtmlProcessor *processor)
{
    if (!m_GlobalProcessors)
    {
        m_GlobalProcessors = new wxHtmlProcessorList;
    }
    wxHtmlProcessorList::compatibility_iterator node;

    for (node = m_GlobalProcessors->GetFirst(); node; node = node->GetNext())
    {
        if (processor->GetPriority() > node->GetData()->GetPriority())
        {
            m_GlobalProcessors->Insert(node, processor);
            return;
        }
    }
    m_GlobalProcessors->Append(processor);
}



wxList wxHtmlWindow::m_Filters;
wxHtmlFilter *wxHtmlWindow::m_DefaultFilter = NULL;
wxHtmlProcessorList *wxHtmlWindow::m_GlobalProcessors = NULL;

void wxHtmlWindow::CleanUpStatics()
{
    wxDELETE(m_DefaultFilter);
    WX_CLEAR_LIST(wxList, m_Filters);
    if (m_GlobalProcessors)
        WX_CLEAR_LIST(wxHtmlProcessorList, *m_GlobalProcessors);
    wxDELETE(m_GlobalProcessors);
}



void wxHtmlWindow::AddFilter(wxHtmlFilter *filter)
{
    m_Filters.Append(filter);
}


bool wxHtmlWindow::IsSelectionEnabled() const
{
#if wxUSE_CLIPBOARD
    return !(m_Style & wxHW_NO_SELECTION);
#else
    return false;
#endif
}


#if wxUSE_CLIPBOARD
wxString wxHtmlWindow::DoSelectionToText(wxHtmlSelection *sel)
{
    if ( !sel )
        return wxEmptyString;

    wxClientDC dc(this);

    const wxHtmlCell *end = sel->GetToCell();
    wxString text;
    wxHtmlTerminalCellsInterator i(sel->GetFromCell(), end);
    if ( i )
    {
        text << i->ConvertToText(sel);
        ++i;
    }
    const wxHtmlCell *prev = *i;
    while ( i )
    {
        if ( prev->GetParent() != i->GetParent() )
            text << _T('\n');
        text << i->ConvertToText(*i == end ? sel : NULL);
        prev = *i;
        ++i;
    }
    return text;
}

wxString wxHtmlWindow::ToText()
{
    if (m_Cell)
    {
        wxHtmlSelection sel;
        sel.Set(m_Cell->GetFirstTerminal(), m_Cell->GetLastTerminal());
        return DoSelectionToText(&sel);
    }
    else
        return wxEmptyString;
}

#endif // wxUSE_CLIPBOARD

bool wxHtmlWindow::CopySelection(ClipboardType t)
{
#if wxUSE_CLIPBOARD
    if ( m_selection )
    {
#if defined(__UNIX__) && !defined(__WXMAC__)
        wxTheClipboard->UsePrimarySelection(t == Primary);
#else // !__UNIX__
        // Primary selection exists only under X11, so don't do anything under
        // the other platforms when we try to access it
        //
        // TODO: this should be abstracted at wxClipboard level!
        if ( t == Primary )
            return false;
#endif // __UNIX__/!__UNIX__

        if ( wxTheClipboard->Open() )
        {
            const wxString txt(SelectionToText());
            wxTheClipboard->SetData(new wxTextDataObject(txt));
            wxTheClipboard->Close();
            wxLogTrace(_T("wxhtmlselection"),
                       _("Copied to clipboard:\"%s\""), txt.c_str());

            return true;
        }
    }
#else
    wxUnusedVar(t);
#endif // wxUSE_CLIPBOARD

    return false;
}


void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
{
    const wxMouseEvent *e = link.GetEvent();
    if (e == NULL || e->LeftUp())
        LoadPage(link.GetHref());
}

void wxHtmlWindow::OnCellClicked(wxHtmlCell *cell,
                                 wxCoord x, wxCoord y,
                                 const wxMouseEvent& event)
{
    wxCHECK_RET( cell, _T("can't be called with NULL cell") );

    cell->OnMouseClick(this, x, y, event);
}

void wxHtmlWindow::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell),
                                    wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
{
    // do nothing here
}

void wxHtmlWindow::OnEraseBackground(wxEraseEvent& event)
{
    if ( !m_bmpBg.Ok() )
    {
        // don't even skip the event, if we don't have a bg bitmap we're going
        // to overwrite background in OnPaint() below anyhow, so letting the
        // default handling take place would only result in flicker, just set a
        // flag to erase the background below
        m_eraseBgInOnPaint = true;
        return;
    }

    wxDC& dc = *event.GetDC();

    // if the image is not fully opaque, we have to erase the background before
    // drawing it, however avoid doing it for opaque images as this would just
    // result in extra flicker without any other effect as background is
    // completely covered anyhow
    if ( m_bmpBg.GetMask() )
    {
        dc.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID));
        dc.Clear();
    }

    const wxSize sizeWin(GetClientSize());
    const wxSize sizeBmp(m_bmpBg.GetWidth(), m_bmpBg.GetHeight());
    for ( wxCoord x = 0; x < sizeWin.x; x += sizeBmp.x )
    {
        for ( wxCoord y = 0; y < sizeWin.y; y += sizeBmp.y )
        {
            dc.DrawBitmap(m_bmpBg, x, y, true /* use mask */);
        }
    }
}

void wxHtmlWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
{
    wxPaintDC dc(this);

    if (m_tmpCanDrawLocks > 0 || m_Cell == NULL)
        return;

    int x, y;
    GetViewStart(&x, &y);
    wxRect rect = GetUpdateRegion().GetBox();
    wxSize sz = GetSize();

    wxMemoryDC dcm;
    if ( !m_backBuffer )
        m_backBuffer = new wxBitmap(sz.x, sz.y);
    dcm.SelectObject(*m_backBuffer);

    if ( m_eraseBgInOnPaint )
    {
        dcm.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID));
        dcm.Clear();

        m_eraseBgInOnPaint = false;
    }
    else // someone has already erased the background, keep it
    {
        // preserve the existing background, otherwise we'd erase anything the
        // user code had drawn in its EVT_ERASE_BACKGROUND handler when we do
        // the Blit back below
        dcm.Blit(0, rect.GetTop(),
                 sz.x, rect.GetBottom() - rect.GetTop() + 1,
                 &dc,
                 0, rect.GetTop());
    }

    PrepareDC(dcm);
    dcm.SetMapMode(wxMM_TEXT);
    dcm.SetBackgroundMode(wxTRANSPARENT);

    wxHtmlRenderingInfo rinfo;
    wxDefaultHtmlRenderingStyle rstyle;
    rinfo.SetSelection(m_selection);
    rinfo.SetStyle(&rstyle);
    m_Cell->Draw(dcm, 0, 0,
                 y * wxHTML_SCROLL_STEP + rect.GetTop(),
                 y * wxHTML_SCROLL_STEP + rect.GetBottom(),
                 rinfo);

//#define DEBUG_HTML_SELECTION
#ifdef DEBUG_HTML_SELECTION
    {
    int xc, yc, x, y;
    wxGetMousePosition(&xc, &yc);
    ScreenToClient(&xc, &yc);
    CalcUnscrolledPosition(xc, yc, &x, &y);
    wxHtmlCell *at = m_Cell->FindCellByPos(x, y);
    wxHtmlCell *before =
        m_Cell->FindCellByPos(x, y, wxHTML_FIND_NEAREST_BEFORE);
    wxHtmlCell *after =
        m_Cell->FindCellByPos(x, y, wxHTML_FIND_NEAREST_AFTER);

    dcm.SetBrush(*wxTRANSPARENT_BRUSH);
    dcm.SetPen(*wxBLACK_PEN);
    if (at)
        dcm.DrawRectangle(at->GetAbsPos(),
                          wxSize(at->GetWidth(),at->GetHeight()));
    dcm.SetPen(*wxGREEN_PEN);
    if (before)
        dcm.DrawRectangle(before->GetAbsPos().x+1, before->GetAbsPos().y+1,
                          before->GetWidth()-2,before->GetHeight()-2);
    dcm.SetPen(*wxRED_PEN);
    if (after)
        dcm.DrawRectangle(after->GetAbsPos().x+2, after->GetAbsPos().y+2,
                          after->GetWidth()-4,after->GetHeight()-4);
    }
#endif

    dcm.SetDeviceOrigin(0,0);
    dc.Blit(0, rect.GetTop(),
            sz.x, rect.GetBottom() - rect.GetTop() + 1,
            &dcm,
            0, rect.GetTop());
}




void wxHtmlWindow::OnSize(wxSizeEvent& event)
{
    wxDELETE(m_backBuffer);

    wxScrolledWindow::OnSize(event);
    CreateLayout();

    // Recompute selection if necessary:
    if ( m_selection )
    {
        m_selection->Set(m_selection->GetFromCell(),
                         m_selection->GetToCell());
        m_selection->ClearPrivPos();
    }

    Refresh();
}

⌨️ 快捷键说明

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