Discussion:
Rich text in a wxGrid cell
Iwbnwif Yiw
2014-04-23 09:57:43 UTC
Permalink
I have a wxGrid and in some cells I would like to display rich text.

To be precise I would like to have the ability to display text which has
different font attributes (bold, italic etc.), bulleted lists, numbered
lists (including hierarchical lists), hyperlinks and images within a cell.
So 'rich text' could also be (for example) HTML.

Probably the total number of cells could reach 10,000 but only 20 or so
would be visible at any one time.

I need to be able to edit the text, but I don't propose to have in-cell
editing.

My initial thoughts are as follows:

- Use wxRichTextCtrl as an editor and save the contents (XML) of each
cell to a std::vector<wxString>
- Write a custom wxGridCellRenderer that instantiates a
wxRichTextBuffer, loads the text from the XML string and uses
wxRichTextBuffer::Draw to draw the contents within the cell's rect

I have taken cues from src/richtextprint.cpp for this.

However if I understand correctly, although the wxGridCellRender would be
reference counted, for each cell a new instance of wxRichTextBuffer would
be created (potentially 10,000) which seems a bit inefficient.

Alternatively I could create a pool of wxRichTextBuffers and load the XML
for the visible cells on-the-fly, but this might make scrolling slow.

I do plan to do some experimentation and see how it goes, but first wanted
to ask the list if there is a better way of doing this :)

Thanks in advance!
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Vadim Zeitlin
2014-04-23 13:45:02 UTC
Permalink
On Wed, 23 Apr 2014 02:57:43 -0700 (PDT) Iwbnwif Yiw wrote:

IY> I have a wxGrid and in some cells I would like to display rich text.
IY>
IY> To be precise I would like to have the ability to display text which has
IY> different font attributes (bold, italic etc.), bulleted lists, numbered
IY> lists (including hierarchical lists), hyperlinks and images within a cell.
IY> So 'rich text' could also be (for example) HTML.

I don't know much about wxRTC, but you should be able to achieve what you
want with wxHTML. Basically just implement your own renderer which would
use wxHtmlParser::Parse() to get a wxHtmlContainerCell and then call Draw()
on it (with some extra preparation, see wxHtmlWindow::OnPaint()).

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Iwbnwif Yiw
2014-04-23 22:07:56 UTC
Permalink
Post by Vadim Zeitlin
Basically just implement your own renderer which would
use wxHtmlParser::Parse() to get a wxHtmlContainerCell and then call Draw()
on it (with some extra preparation, see wxHtmlWindow::OnPaint()).
Vadim, thank you for your answer!

This sounds like a really tidy solution. I will need to implement a basic
HTML editor, but for time being may try to use TinyMCE or similar inside a
wxWebView.

Unfortunately for some reason I just can't seem to get wxHtmlParser to work
properly (actually I am trying wxHtmlWinParser - is that what you meant?)

FWIW this is what I have inside a paint event handler on a wxPanel (for
stripped down test purposes).

void myPanel::OnPaint(wxPaintEvent& event)
{
wxString html = "<b>Hello world</b> this is a test";

wxLogMessage ("Painting: " + html);

wxPaintDC dc (this);
PrepareDC(dc);
dc.Clear();

wxHtmlWinParser parser;
parser.SetDC(&dc);
parser.SetStandardFonts(10, "helvetica", "helvetica");

wxHtmlContainerCell* cell;
cell = NULL;

cell = (wxHtmlContainerCell*)parser.Parse(html);

cell->SetBackgroundColour(*wxRED);
cell->SetIndent(1, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
cell->SetAlignHor(wxHTML_ALIGN_CENTER);

// draw the HTML window contents
dc.SetMapMode(wxMM_TEXT);
dc.SetBackgroundMode(wxTRANSPARENT);
dc.SetLayoutDirection(GetLayoutDirection());

wxHtmlRenderingInfo rinfo;

wxDefaultHtmlRenderingStyle rstyle;
rinfo.SetSelection(NULL);
rinfo.SetStyle(&rstyle);

cell->Draw(dc, 10, 10, 0, 3000, rinfo);
}

This is what I have understood from wxHtmlWindow::OnPaint and a few other
places in htmlwin.cpp

However I can get something working using wxHtmlDCRenderer as follows
(inside the same paint event handler).

void myPanel::OnPaint(wxPaintEvent& event)
{
wxString html = "<b>Hello world</b> this is a test";

wxLogMessage ("Painting: " + html);

wxPaintDC dc (this);

PrepareDC(dc);

dc.Clear();

wxHtmlDCRenderer renderer;

renderer.SetDC (&dc);
renderer.SetSize (100, 100);
renderer.SetHtmlText (m_HTML);
wxArrayInt value;

renderer.Render (0, 0, value);
}

So I wonder if wxHtmlDCRenderer is an okay way to go, or if there is
something obvious that I have missed when using wxHtmlWinParser?

Thanks again!
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Iwbnwif Yiw
2014-04-24 09:33:45 UTC
Permalink
Post by Iwbnwif Yiw
So I wonder if wxHtmlDCRenderer is an okay way to go, or if there is
something obvious that I have missed when using wxHtmlWinParser?
After further inspection of htmprint.cpp I think I now know the answer to
both these questions :)

1) wxHtmlDCRenderer looks to be an ideal way to do this
2) I missed cell->Layout (width) from the wxHtmlWinParser approach.

However now I have found a couple of limitations that I will need to work
around (unless someone already has a solution):

1) wxHTML doesn't implement outline list types <OL TYPE="i"> etc.
2) wxHTML doesn't implement margins <P style="margin-left:10px">
unfortunately.

Looking at m_list.cpp the first one should be relatively straightforward
but I think the second one is harder...
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Vadim Zeitlin
2014-04-24 12:33:42 UTC
Permalink
On Thu, 24 Apr 2014 02:33:45 -0700 (PDT) Iwbnwif Yiw wrote:

IY> After further inspection of htmprint.cpp I think I now know the answer to
IY> both these questions :)
IY>
IY> 1) wxHtmlDCRenderer looks to be an ideal way to do this

Yes, indeed, I simply didn't know (or completely forgot) about this class,
sorry for the wrong advice.

IY> However now I have found a couple of limitations that I will need to work
IY> around (unless someone already has a solution):
IY>
IY> 1) wxHTML doesn't implement outline list types <OL TYPE="i"> etc.
IY> 2) wxHTML doesn't implement margins <P style="margin-left:10px">
IY> unfortunately.
IY>
IY> Looking at m_list.cpp the first one should be relatively straightforward
IY> but I think the second one is harder...

Yes, wxHTML doesn't really have any CSS support, although there is a small
bit of it for <span> (see wxHtmlStyleParams). And I suspect handling the
margin property might indeed be non trivial, although I really don't know
this code well enough to be certain.

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Iwbnwif Yiw
2014-04-24 13:21:52 UTC
Permalink
Post by Vadim Zeitlin
Yes, indeed, I simply didn't know (or completely forgot) about this class,
sorry for the wrong advice.
Lol, not at all - it was your advice that enabled me to find it - thank you!
Post by Vadim Zeitlin
Yes, wxHTML doesn't really have any CSS support, although there is a small
bit of it for <span> (see wxHtmlStyleParams). And I suspect handling the
margin property might indeed be non trivial
There is a wxHtmlCell::SetIndent method that might help. Thinking aloud
really, much more research needed.
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Loading...