255 lines
8.2 KiB
C++
255 lines
8.2 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/generic/markuptext.cpp
|
|
// Purpose: wxMarkupText implementation
|
|
// Author: Vadim Zeitlin
|
|
// Created: 2011-02-21
|
|
// RCS-ID: $Id: markuptext.cpp 67075 2011-02-27 18:36:48Z VZ $
|
|
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// for compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_MARKUP
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/gdicmn.h"
|
|
#include "wx/control.h"
|
|
#include "wx/dc.h"
|
|
#endif // WX_PRECOMP
|
|
|
|
#include "wx/generic/private/markuptext.h"
|
|
|
|
#include "wx/private/markupparserattr.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxMarkupParserMeasureOutput: measure the extends of a markup string.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxMarkupParserMeasureOutput : public wxMarkupParserAttrOutput
|
|
{
|
|
public:
|
|
// Initialize the base class with the font to use. As we don't care about
|
|
// colours (which don't affect the text measurements), don't bother to
|
|
// specify them at all.
|
|
wxMarkupParserMeasureOutput(wxDC& dc, int *visibleHeight)
|
|
: wxMarkupParserAttrOutput(dc.GetFont(), wxColour(), wxColour()),
|
|
m_dc(dc),
|
|
m_visibleHeight(visibleHeight)
|
|
{
|
|
if ( visibleHeight )
|
|
*visibleHeight = 0;
|
|
}
|
|
|
|
const wxSize& GetSize() const { return m_size; }
|
|
|
|
|
|
virtual void OnText(const wxString& text_)
|
|
{
|
|
const wxString text(wxControl::RemoveMnemonics(text_));
|
|
|
|
// TODO-MULTILINE-MARKUP: Must use GetMultiLineTextExtent().
|
|
const wxSize size = m_dc.GetTextExtent(text);
|
|
|
|
m_size.x += size.x;
|
|
if ( size.y > m_size.y )
|
|
m_size.y = size.y;
|
|
|
|
if ( m_visibleHeight )
|
|
{
|
|
wxFontMetrics tm = m_dc.GetFontMetrics();
|
|
int visibleHeight = tm.ascent - tm.internalLeading;
|
|
if ( *m_visibleHeight < visibleHeight )
|
|
*m_visibleHeight = visibleHeight;
|
|
}
|
|
}
|
|
|
|
virtual void OnAttrStart(const Attr& attr)
|
|
{
|
|
m_dc.SetFont(attr.font);
|
|
}
|
|
|
|
virtual void OnAttrEnd(const Attr& WXUNUSED(attr))
|
|
{
|
|
m_dc.SetFont(GetFont());
|
|
}
|
|
|
|
private:
|
|
wxDC& m_dc;
|
|
|
|
// The values that we compute.
|
|
wxSize m_size;
|
|
int * const m_visibleHeight; // may be NULL
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxMarkupParserMeasureOutput);
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxMarkupParserRenderOutput: render a markup string.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxMarkupParserRenderOutput : public wxMarkupParserAttrOutput
|
|
{
|
|
public:
|
|
// Notice that the bottom of rectangle passed to our ctor is used as the
|
|
// baseline for the text we draw, i.e. it needs to be adjusted to exclude
|
|
// descent by the caller.
|
|
wxMarkupParserRenderOutput(wxDC& dc,
|
|
const wxRect& rect,
|
|
int flags)
|
|
: wxMarkupParserAttrOutput(dc.GetFont(),
|
|
dc.GetTextForeground(),
|
|
wxColour()),
|
|
m_dc(dc),
|
|
m_rect(rect),
|
|
m_flags(flags)
|
|
{
|
|
m_pos = m_rect.x;
|
|
|
|
// We don't initialize the base class initial text background colour to
|
|
// the valid value because we want to be able to detect when we revert
|
|
// to the "absence of background colour" and set the background mode to
|
|
// be transparent in OnAttrStart() below. But do remember it to be able
|
|
// to restore it there later -- this doesn't affect us as the text
|
|
// background isn't used anyhow when the background mode is transparent
|
|
// but it might affect the caller if it sets the background mode to
|
|
// opaque and draws some text after using us.
|
|
m_origTextBackground = dc.GetTextBackground();
|
|
}
|
|
|
|
virtual void OnText(const wxString& text_)
|
|
{
|
|
wxString text;
|
|
int indexAccel = wxControl::FindAccelIndex(text_, &text);
|
|
if ( !(m_flags & wxMarkupText::Render_ShowAccels) )
|
|
indexAccel = wxNOT_FOUND;
|
|
|
|
// Adjust the position (unfortunately we need to do this manually as
|
|
// there is no notion of current text position in wx API) rectangle to
|
|
// ensure that all text segments use the same baseline (as there is
|
|
// nothing equivalent to Windows SetTextAlign(TA_BASELINE) neither).
|
|
wxRect rect(m_rect);
|
|
rect.x = m_pos;
|
|
|
|
int descent;
|
|
m_dc.GetTextExtent(text, &rect.width, &rect.height, &descent);
|
|
rect.height -= descent;
|
|
rect.y += m_rect.height - rect.height;
|
|
|
|
wxRect bounds;
|
|
m_dc.DrawLabel(text, wxBitmap(),
|
|
rect, wxALIGN_LEFT | wxALIGN_TOP,
|
|
indexAccel,
|
|
&bounds);
|
|
|
|
// TODO-MULTILINE-MARKUP: Must update vertical position too.
|
|
m_pos += bounds.width;
|
|
}
|
|
|
|
virtual void OnAttrStart(const Attr& attr)
|
|
{
|
|
m_dc.SetFont(attr.font);
|
|
if ( attr.foreground.IsOk() )
|
|
m_dc.SetTextForeground(attr.foreground);
|
|
|
|
if ( attr.background.IsOk() )
|
|
{
|
|
// Setting the background colour is not enough, we must also change
|
|
// the mode to ensure that it is actually used.
|
|
m_dc.SetBackgroundMode(wxSOLID);
|
|
m_dc.SetTextBackground(attr.background);
|
|
}
|
|
}
|
|
|
|
virtual void OnAttrEnd(const Attr& attr)
|
|
{
|
|
// We always restore the font because we always change it...
|
|
m_dc.SetFont(GetFont());
|
|
|
|
// ...but we only need to restore the colours if we had changed them.
|
|
if ( attr.foreground.IsOk() )
|
|
m_dc.SetTextForeground(GetAttr().foreground);
|
|
|
|
if ( attr.background.IsOk() )
|
|
{
|
|
wxColour background = GetAttr().background;
|
|
if ( !background.IsOk() )
|
|
{
|
|
// Invalid background colour indicates that the background
|
|
// should actually be made transparent and in this case the
|
|
// actual value of background colour doesn't matter but we also
|
|
// restore it just in case, see comment in the ctor.
|
|
m_dc.SetBackgroundMode(wxTRANSPARENT);
|
|
background = m_origTextBackground;
|
|
}
|
|
|
|
m_dc.SetTextBackground(background);
|
|
}
|
|
}
|
|
|
|
private:
|
|
wxDC& m_dc;
|
|
const wxRect m_rect;
|
|
const int m_flags;
|
|
|
|
wxColour m_origTextBackground;
|
|
|
|
// Current horizontal text output position.
|
|
//
|
|
// TODO-MULTILINE-MARKUP: Must keep vertical position too.
|
|
int m_pos;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxMarkupParserRenderOutput);
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
// ============================================================================
|
|
// wxMarkupText implementation
|
|
// ============================================================================
|
|
|
|
wxSize wxMarkupText::Measure(wxDC& dc, int *visibleHeight) const
|
|
{
|
|
wxMarkupParserMeasureOutput out(dc, visibleHeight);
|
|
wxMarkupParser parser(out);
|
|
if ( !parser.Parse(m_markup) )
|
|
{
|
|
wxFAIL_MSG( "Invalid markup" );
|
|
return wxDefaultSize;
|
|
}
|
|
|
|
return out.GetSize();
|
|
}
|
|
|
|
void wxMarkupText::Render(wxDC& dc, const wxRect& rect, int flags)
|
|
{
|
|
// We want to center the above-baseline parts of the letter vertically, so
|
|
// we use the visible height and not the total height (which includes
|
|
// descent and internal leading) here.
|
|
int visibleHeight;
|
|
wxRect rectText(rect.GetPosition(), Measure(dc, &visibleHeight));
|
|
rectText.height = visibleHeight;
|
|
|
|
wxMarkupParserRenderOutput out(dc, rectText.CentreIn(rect), flags);
|
|
wxMarkupParser parser(out);
|
|
parser.Parse(m_markup);
|
|
}
|
|
|
|
#endif // wxUSE_MARKUP
|