]> git.saurik.com Git - wxWidgets.git/blobdiff - docs/latex/wx/richtextoverview.tex
Ref counting overview.
[wxWidgets.git] / docs / latex / wx / richtextoverview.tex
index e9a5116a6df538eebf8c502777a1529c88d771b7..97c7254a9c0f8ab5daf3d3c0a3c1c5f5c823b02e 100644 (file)
@@ -5,12 +5,42 @@ Classes: \helpref{wxRichTextCtrl}{wxrichtextctrl}, \helpref{wxRichTextBuffer}{wx
 \helpref{wxRichTextCharacterStyleDefinition}{wxrichtextcharacterstyledefinition}, 
 \helpref{wxRichTextParagraphStyleDefinition}{wxrichtextparagraphstyledefinition}, 
 \helpref{wxRichTextStyleSheet}{wxrichtextstylesheet}, 
+\helpref{wxRichTextStyleComboCtrl}{wxrichtextstylecomboctrl}, 
 \helpref{wxRichTextStyleListBox}{wxrichtextstylelistbox}, 
 \helpref{wxRichTextEvent}{wxrichtextevent}, \helpref{wxRichTextRange}{wxrichtextrange}, 
 \helpref{wxRichTextFileHandler}{wxrichtextfilehandler}, \helpref{wxRichTextHTMLHandler}{wxrichtexthtmlhandler}, 
-\helpref{wxRichTextXMLHandler}{wxrichtextxmlhandler}
+\helpref{wxRichTextXMLHandler}{wxrichtextxmlhandler}, 
+\helpref{wxRichTextFormattingDialog}{wxrichtextformattingdialog}, 
+\helpref{wxSymbolPickerDialog}{wxsymbolpickerdialog}
 
-wxRichTextCtrl provides a generic implementation of a rich text editor
+wxRichTextCtrl provides a generic implementation of a rich text editor that can handle different character
+styles, paragraph formatting, and images. It's aimed at editing 'natural' language text - if you need an editor that supports code editing,
+wxStyledTextCtrl is a better choice.
+
+Despite its name, it cannot currently read or write RTF (rich text format) files. Instead, it
+uses its own XML format, and can also read and write plain text. In future we expect to provide
+RTF file capabilities. Custom file formats can be supported by creating additional
+file handlers and registering them with the control.
+
+wxRichTextCtrl is largely compatible with the wxTextCtrl API, but extends it where necessary.
+The control can be used where the native rich text capabilities of wxTextCtrl are not
+adequate (this is particularly true on Windows) and where more direct access to
+the content representation is required. It is difficult and inefficient to read
+the style information in a wxTextCtrl, whereas this information is readily
+available in wxRichTextCtrl. Since it's written in pure wxWidgets, any customizations
+you make to wxRichTextCtrl will be reflected on all platforms.
+
+There are of course a few disadvantages to using wxRichTextCtrl. It is not native,
+so does not behave exactly as a native wxTextCtrl, although common editing conventions
+are followed. Users may miss the built-in spelling correction on Mac OS X, or any
+special character input that may be provided by the native control. It would also
+be a bad choice if intended users rely on screen readers that would be unhappy
+with non-native text input implementation. You might mitigate this by providing
+the choice between wxTextCtrl and wxRichTextCtrl, with fewer features in the
+former case.
+
+wxRichTextCtrl does not yet support printing directly, but content can be converted
+to HTML which can then be used with \helpref{wxHtmlEasyPrinting}{wxhtmleasyprinting}.
 
 The following screenshot shows the wxRichTextCtrl sample in action:
 
@@ -18,17 +48,353 @@ $$\image{8cm;0cm}{richtextctrl.gif}$$
 
 \wxheading{Example}\label{wxrichtextctrlexample}
 
-TODO
+The following code is taken from the sample, and adds text and styles to a rich text control programmatically.
 
 {\small
 \begin{verbatim}
+    wxRichTextCtrl* richTextCtrl = new wxRichTextCtrl(splitter, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS);
+
+    wxFont textFont = wxFont(12, wxROMAN, wxNORMAL, wxNORMAL);
+    wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
+    wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL);
+
+    wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
+
+    m_richTextCtrl->SetFont(font);
+
+    wxRichTextCtrl& r = richTextCtrl;
+
+    r.BeginSuppressUndo();
+
+    r.BeginParagraphSpacing(0, 20);
+
+    r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
+    r.BeginBold();
+
+    r.BeginFontSize(14);
+    r.WriteText(wxT("Welcome to wxRichTextCtrl, a wxWidgets control for editing and presenting styled text and images"));
+    r.EndFontSize();
+    r.Newline();
+
+    r.BeginItalic();
+    r.WriteText(wxT("by Julian Smart"));
+    r.EndItalic();
+
+    r.EndBold();
+
+    r.Newline();
+    r.WriteImage(wxBitmap(zebra_xpm));
+
+    r.EndAlignment();
+
+    r.Newline();
+    r.Newline();
+
+    r.WriteText(wxT("What can you do with this thing? "));
+    r.WriteImage(wxBitmap(smiley_xpm));
+    r.WriteText(wxT(" Well, you can change text "));
+
+    r.BeginTextColour(wxColour(255, 0, 0));
+    r.WriteText(wxT("colour, like this red bit."));
+    r.EndTextColour();
+
+    r.BeginTextColour(wxColour(0, 0, 255));
+    r.WriteText(wxT(" And this blue bit."));
+    r.EndTextColour();
+
+    r.WriteText(wxT(" Naturally you can make things "));
+    r.BeginBold();
+    r.WriteText(wxT("bold "));
+    r.EndBold();
+    r.BeginItalic();
+    r.WriteText(wxT("or italic "));
+    r.EndItalic();
+    r.BeginUnderline();
+    r.WriteText(wxT("or underlined."));
+    r.EndUnderline();
+
+    r.BeginFontSize(14);
+    r.WriteText(wxT(" Different font sizes on the same line is allowed, too."));
+    r.EndFontSize();
+
+    r.WriteText(wxT(" Next we'll show an indented paragraph."));
+
+    r.BeginLeftIndent(60);
+    r.Newline();
+
+    r.WriteText(wxT("Indented paragraph."));
+    r.EndLeftIndent();
+
+    r.Newline();
+
+    r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
+
+    r.BeginLeftIndent(100, -40);
+    r.Newline();
+
+    r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter."));
+    r.EndLeftIndent();
+
+    r.Newline();
+
+    r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
+
+    r.BeginNumberedBullet(1, 100, 60);
+    r.Newline();
+
+    r.WriteText(wxT("This is my first item. Note that wxRichTextCtrl doesn't automatically do numbering, but this will be added later."));
+    r.EndNumberedBullet();
+
+    r.BeginNumberedBullet(2, 100, 60);
+    r.Newline();
+
+    r.WriteText(wxT("This is my second item."));
+    r.EndNumberedBullet();
+
+    r.Newline();
+
+    r.WriteText(wxT("The following paragraph is right-indented:"));
+
+    r.BeginRightIndent(200);
+    r.Newline();
+
+    r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
+    r.EndRightIndent();
+
+    r.Newline();
+
+    wxArrayInt tabs;
+    tabs.Add(400);
+    tabs.Add(600);
+    tabs.Add(800);
+    tabs.Add(1000);
+    wxTextAttrEx attr;
+    attr.SetFlags(wxTEXT_ATTR_TABS);
+    attr.SetTabs(tabs);
+    r.SetDefaultStyle(attr);
+    
+    r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
+
+    r.Newline();
+    r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
+
+    r.BeginSymbolBullet(wxT('*'), 100, 60);
+    r.Newline();
+    r.WriteText(wxT("Compatibility with wxTextCtrl API"));
+    r.EndSymbolBullet();
+
+    r.WriteText(wxT("Note: this sample content was generated programmatically from within the MyFrame constructor in the demo. The images were loaded from inline XPMs. Enjoy wxRichTextCtrl!"));
+
+    r.EndSuppressUndo();
 \end{verbatim}
 }
 
-\wxheading{Programming with wxRichTextCtrl}
+\subsection{Programming with wxRichTextCtrl}
+
+\subsubsection{Starting to use wxRichTextCtrl}
+
+You need to include {\tt <wx/richtext/richtextctrl.h>} in your source, and link
+with the appropriate wxWidgets library with {\tt richtext} suffix. Put the rich text
+library first in your link line to avoid unresolved symbols.
+
+Then you can create a wxRichTextCtrl, with the wxWANT\_CHARS style if you want tabs to
+be processed by the control rather than being used for navigation between controls.
+
+\subsubsection{wxRichTextCtrl and styles}
+
+Styling attributes are represented by one of three classes: \helpref{wxTextAttr}{wxtextattr}, \helpref{wxTextAttrEx}{wxtextattrex} and \helpref{wxRichTextAttr}{wxrichtextattr}.
+wxTextAttr is shared across all controls that are derived from wxTextCtrl and
+can store basic character and paragraph attributes. wxTextAttrEx derives
+from wxTextAttr and adds some further attributes that are only supported
+by wxRichTextCtrl. Finally, wxRichTextAttr is a more efficient version
+of wxTextAttrEx that doesn't use a wxFont object and can be used to
+query styles more quickly. wxTextAttrEx and wxRichTextAttr are largely
+interchangeable and have suitable conversion operators between them.
+
+When setting a style, the flags of the attribute object determine which
+attributes are applied. When querying a style, the passed flags are ignored
+except (optionally) to determine whether attributes should be retrieved from
+character content or from the paragraph object.
+
+wxRichTextCtrl takes a layered approach to styles, so that different parts of
+the content may be responsible for contributing different attributes to the final
+style you see on the screen.
+
+There are four main notions of style within a control:
+
+\begin{enumerate}\itemsep=0pt
+\item {\bf Basic style:} the fundamental style of a control, onto which any other
+styles are layered. It provides default attributes, and changing the basic style
+may immediately change the look of the content depending on what other styles
+the content uses. Calling wxRichTextCtrl::SetFont changes the font for the basic style.
+The basic style is set with \helpref{wxRichTextCtrl::SetBasicStyle}{wxrichtextctrlsetbasicstyle}.
+\item {\bf Paragraph style:} each paragraph has attributes that are set independently
+from other paragraphs and independently from the content within the paragraph.
+Normally, these attributes are paragraph-related, such as alignment and indentation,
+but it is possible to set character attributes too.
+The paragraph style can be set independently of its content by passing wxRICHTEXT\_SETSTYLE\_PARAGRAPHS\_ONLY
+to \helpref{wxRichTextCtrl::SetStyleEx}{wxrichtextctrlsetstyleex}.
+\item {\bf Character style:} characters within each paragraph can have attributes.
+A single character, or a run of characters, can have a particular set of attributes.
+The character style can be with \helpref{wxRichTextCtrl::SetStyle}{wxrichtextctrlsetstyle} or 
+\helpref{wxRichTextCtrl::SetStyleEx}{wxrichtextctrlsetstyleex}.
+\item {\bf Default style:} this is the `current' style that determines the
+style of content that is subsequently typed, pasted or programmatically inserted.
+The default style is set with \helpref{wxRichTextCtrl::SetDefaultStyle}{wxrichtextctrlsetdefaultstyle}.
+\end{enumerate}
+
+What you see on the screen is the dynamically {\it combined} style, found by merging
+the first three of the above style types (the fourth is only a guide for future content
+insertion and therefore does not affect the currently displayed content).
+
+To make all this more concrete, here are examples of where you might set these different
+styles:
+
+\begin{enumerate}\itemsep=0pt
+\item You might set the {\bf basic style} to have a Times Roman font in 12 point,
+left-aligned, with two millimetres of spacing after each paragraph.
+\item You might set the {\bf paragraph style} (for one particular paragraph) to
+be centred.
+\item You might set the {\bf character style} of one particular word to bold.
+\item You might set the {\bf default style} to be underlined, for subsequent
+inserted text.
+\end{enumerate}
+
+Naturally you can do any of these things either using your own UI, or programmatically.
+
+The basic wxTextCtrl doesn't make the same distinctions as wxRichTextCtrl regarding
+attribute storage. So we need finer control when setting and retrieving
+attributes. \helpref{wxRichTextCtrl::SetStyleEx}{wxrichtextctrlsetstyleex} takes a {\it flags} parameter:
+
+\begin{itemize}\itemsep=0pt
+\item wxRICHTEXT\_SETSTYLE\_OPTIMIZE specifies that the style should be changed only if
+the combined attributes are different from the attributes for the current object. This is important when
+applying styling that has been edited by the user, because he has just edited the {\it combined} (visible)
+style, and wxRichTextCtrl wants to leave unchanged attributes associated with their original objects
+instead of applying them to both paragraph and content objects.
+\item wxRICHTEXT\_SETSTYLE\_PARAGRAPHS\_ONLY specifies that only paragraph objects within the given range
+should take on the attributes.
+\item wxRICHTEXT\_SETSTYLE\_CHARACTERS\_ONLY specifies that only content objects (text or images) within the given range
+should take on the attributes.
+\item wxRICHTEXT\_SETSTYLE\_WITH\_UNDO specifies that the operation should be undoable.
+\end{itemize}
+
+It's great to be able to change arbitrary attributes in a wxRichTextCtrl, but
+it can be unwieldy for the user or programmer to set attributes separately. Word processors have collections
+of styles that you can tailor or use as-is, and this means that you can set a heading with one click
+instead of marking text in bold, specifying a large font size, and applying a certain
+paragraph spacing and alignment for every such heading. Similarly,
+wxWidgets provides a class called \helpref{wxRichTextStyleSheet}{wxrichtextstylesheet} which manages style definitions
+(\helpref{wxRichTextParagraphStyleDefinition}{wxrichtextparagraphstyledefinition} and \helpref{wxRichTextCharacterStyleDefinition}{wxrichtextcharacterstyledefinition}).
+Once you have added definitions to a style sheet and associated it with a wxRichTextCtrl,
+you can apply a named definition to a range of text. The classes \helpref{wxRichTextStyleComboCtrl}{wxrichtextstylecomboctrl}\rtfsp
+and \helpref{wxRichTextStyleListBox}{wxrichtextstylelistbox} can be used to present the user with a list
+of styles in a sheet, and apply them to the selected text.
+
+You can reapply a style sheet to the contents of the control, by calling \helpref{wxRichTextCtrl::ApplyStyleSheet}{wxrichtextctrlapplystylesheet}.
+This is useful if the style definitions have changed, and you want the content to reflect this.
+It relies on the fact that when you apply a named style, the style definition name is recorded in the
+content. So ApplyStyleSheet works by finding the paragraph attributes with style names and re-applying the definition's
+attributes to the paragraph. Currently, this works with paragraph style definitions only.
+
+\subsection{wxRichTextCtrl dialogs}\label{wxrichtextctrldialogs}
+
+wxRichTextCtrl comes with standard dialogs to make it easier to implement
+text editing functionality.
+
+\helpref{wxRichTextFormattingDialog}{wxrichtextformattingdialog} can be used
+for character or paragraph formatting, or a combination of both. It's a wxPropertySheetDialog
+with the following available tabs: Font, Indents \& Spacing, Tabs, Bullets, and Style.
+You can select which pages will be shown by supplying flags to the dialog constructor.
+In a character formatting dialog, typically only the Font page will be shown.
+In a paragraph formatting dialog, you'll show the Indents \& Spacing, Tabs and Bullets
+pages. The Style tab is useful when editing a style definition.
+
+You can customize this dialog by providing your own wxRichTextFormattingDialogFactory
+object, which tells the formatting dialog how many pages are supported, what their identifiers
+are, and how to creates the pages.
+
+\helpref{wxSymbolPickerDialog}{wxsymbolpickerdialog} lets the user insert a symbol from
+a specified font. It has no wxRichTextCtrl dependencies besides being included in
+the rich text library.
+
+\subsection{How wxRichTextCtrl is implemented}
+
+Data representation is handled by wxRichTextBuffer, and a wxRichTextCtrl
+always has one such buffer.
+
+The content is represented by a hierarchy of objects, all derived from
+wxRichTextObject. An object might be an image, a fragment of text, a paragraph,
+or a whole buffer. Objects store a wxRichTextAttr containing style information;
+although it contains both paragraph formatting and character style, the
+paragraph style information is ignored by children of a paragraph (only
+character style is relevant to these objects).
+
+The top of the hierarchy is the buffer, a kind of wxRichTextParagraphLayoutBox.
+containing further wxRichTextParagraph objects, each of which can include text,
+images and potentially other types of object.
+
+Each object maintains a range (start and end position) measured
+from the start of the main parent box.
+
+When Layout is called on an object, it is given a size which the object
+must limit itself to, or one or more flexible directions (vertical
+or horizontal). So, for example, a centred paragraph is given the page
+width to play with (minus any margins), but can extend indefinitely
+in the vertical direction. The implementation of Layout caches the calculated
+size and position.
+
+When the buffer is modified, a range is invalidated (marked as requiring
+layout), so that only the minimum amount of layout is performed.
+
+A paragraph of pure text with the same style contains just one further
+object, a wxRichTextPlainText object. When styling is applied to part of
+this object, the object is decomposed into separate objects, one object
+for each different character style. So each object within a paragraph always has
+just one wxRichTextAttr object to denote its character style. Of course, this can
+lead to fragmentation after a lot of edit operations, potentially leading
+to several objects with the same style where just one would do. So
+a Defragment function is called when updating the control's display, to ensure that
+the minimum number of objects is used.
+
+\subsection{wxRichTextCtrl roadmap}
+
+\wxheading{Bugs}
+
+This is an incomplete list of bugs.
+
+\begin{itemize}\itemsep=0pt
+\item Moving the caret up at the beginning of a line sometimes incorrectly positions the
+caret.
+\item As the selection is expanded, the text jumps slightly due to kerning differences between
+drawing a single text string versus drawing several fragments separately. This could
+be improved by using wxDC::GetPartialTextExtents to calculate exactly where the separate fragments
+should be drawn.
+Alternatively, it might be possible to use the difference between the width of text from
+a to b+1, versus the width of the text from a to b added to the width of b to b+1.
+Note that this problem also applies to separation of text fragments due to difference in their attributes.
+\item Selection doesn't work properly for text that contains tabs.
+\end{itemize}
+
+\wxheading{Features}
+
+This is a list of some of the features that have yet to be implemented. Help with them will be appreciated.
 
-TODO
+\begin{itemize}\itemsep=0pt
+\item Printing
+\item RTF input and output
+\item Floating images, with content wrapping around them
+\item A ruler control
+\item Standard editing toolbars
+\item Automatic list numbering
+\item Tables
+\item Text frames
+\item Add ability to show images in wxHTML output (currently uses embedded data suitable only for real browsers)
+\item More complete stylesheet viewer, plus style sheet editing dialogs
+\item Ability to read and write style sheets
+\end{itemize}
 
-\wxheading{How wxRichTextCtrl is implemented}
+There are also things that could be done to take advantage of the underlying text capabilities of the platform;
+higher-level text formatting APIs are available on some platforms, such as Mac OS X, and some of translation from
+high level to low level wxDC API is unnecessary. However this would require additions to the wxWidgets API.
 
-TODO