|
Work with Styles and Stylesheets (in code) |
Top Previous Next |
|
WPTools 5 has powerful possibilities to work with text styles.
This one is one of the most important chapters of this manual since it explains how the styles - which are the heart of WPTools 5 - can be used and controlled.
1) What is a 'style'?
A text style is a collection of text attributes which are used for a certain text unless the text itself overrides the attributes. So if you have a style which defines two properties, the font name and the font size and assign it to some text this text will be displayed in the select font in the selected size. If the text was created to use the font size, ie. 10, this font size will be used and not the font size defined in the style. Please note that borders can not be be defined in styles.
Text styles usually have names, for example 'Headline' or 'Normal'. Using the names you can select a style from the list of styles and assign it to a paragraph. This assignment usually does not modify the attributes of the text. (NOTE A)
2) The demo project (Demos/Tasks/ParStyle):
This demo shows different ways to deal with the styles. You can play with the default attribute and the properties of one if the styles (FIRST) and immediately see the effect.
3) The default attribute
This attribute (or elements of it) will be used for all the text which does not have an attribute ion its own.
In this demo we initialize the default attribute using:
WPRichText1.DefaultAttr.SetFontName(ComboBox1.Text); WPRichText1.DefaultAttr.SetFontSize(WPValueEdit2.Value / 20);
While the demo is running you can change the defined values and immediately see the effect. So all the paragraph styles (FIRST and SECOND) set their own font size - changing the default will not change the display. But if you are changing the font name, you will see the change not only in the first line but also in the 3rd line:
So how is text created which only uses the default attribute?
par := WPRichText1.ActiveText.AppendPar; par.SetText('1) This line uses no style - It uses WPRichText1.DefaultAttr !');
But in general, when you write text into the editor and no specific font was selected - that entry will be 'undefined' and the default will be used.
4) Creating a paragraph style
In this demo we create a style (sty : TWPTextStyle;) like this:
sty := WPRichText1.ParStyles.AddStyle('FIRST');
and then assign properties using the ASet methods:
sty.ASetAddCharStyle(WPSTY_BOLD); sty.ASetFontName('Verdana'); sty.ASet(WPAT_CharFontSize, 13 * 100);
Please see reference for supported WPAT_ codes.
Many customers have asked why the styles do not have properties, such as sty.FontName? The reason for this is that using functions to read and write the properties we can support the <undefined> state. This means that if a font name was not set in a style we can react on that (by using the inherited font name). In general are the ASet... methods used to write a property while the AGet function are used to read it. They usually require a var parameter which will be changed. The result value of an AGet function is TRUE if the property was defined, otherwise it is FALSE. There is also the AGetDef() function which returns the property value itself, if it was not found it returns the default which was passed as parameter. (Read more about ASet)
To use the paragraph style we can set the name par.ABaseStyleName := 'FIRST';
or the style: par.ABaseStyle := sty;
Important: Only the attributes which are not overridden in the paragraph or the character attributes whill be retrieved from the attached style.
This code will simply attach a style, it will not modify any properties of the paragraph or the text in this paragraph. So it is possible that the text does not use certain attributes of the style since they are overridden.
a) To remove the attributes which are defined by a style you can use the method SetStyle which can be used with a style number, a style name or the reference to an item of the ParStyles collection. Two optional parameters control if the paragraph attributes and/or the character attributes should be adjusted to make all style attributes visible. par.SetStyle( 'FIRST' , true, true);
b) If you are working with selected text, you can use the procedure SelectedTextAttr.ClearAttr(false,true) to remove all styles from the selected text, only the paragraph styles will be used.
You can also use SelectedTextAttr.ClearAttrOverride - this will remove the attributes which are used in the paragraph styles. So the attributes which are not override attributes will be preserved, the attributes which will otherwise hide the paragraph style attributes will be removed.
5) Save and restore style sheet in WPCSS format
// Save: Memo1.Text := WPRichText1.ParStyles.GetWPCSS; //or WPRichText1.ParStyles.SaveToFile('c:\stylesheet.wpcss'); // Load: WPRichText1.ParStyles.SetWPCSS(Memo1.Text); WPRichText1.ReformatAll(true,true); //or WPRichText1.ParStyles.LoadFromFile('c:\stylesheet.wpcss'); WPRichText1.ReformatAll(true,true);
6) Creating embedded SPAN objects (Line 3)
Especially to provide strong HTML support WPTools 5 can work with embedded SPAN styles. This are special objects which are embedded into the text. They are always used in pairs, one opening and one closing. The opening object can select a style and the closing object selects the previous settings again.
If you are working with RTF you should not use SPAN objects.
In this demo we create the objects right in the TParagraph object. If you need a less abstract way to work with the objects please check out the 'Code' procedures implemented in TWPRichText. They make it easy to create the objects, for example wrap selected text into a pair of SPAN tags.
par := WPRichText1.ActiveText.AppendPar; pos := par.Insert(0, '3) SECOND STYLE - except for ',0); spanobj_open := par.InsertNewObject(pos,wpobjSPANStyle, true, false); spanobj_open.StyleName := 'FIRST'; inc(pos); pos := par.Insert(pos, '<SPAN "FIRST">',0); spanobj_close := par.InsertNewObject(pos,wpobjSPANStyle, true, true); spanobj_close.SetTag(spanobj_open.NewTag); //<-- tags are used to link start with end! inc(pos); pos := par.Insert(pos, ' - END',0); par.ABaseStyleName := 'SECOND';
The variables spanobj_open and spanobj_close are of type TWPTextObj. They are created by InsertNewObject which requires four parameters: index: Integer; objtype: TWPTextObjType; HasClosing, IsClosing: Boolean
Please note how the value for 'IsClosing' is alternated the the demo source code. "pos" is an integer value which is the index into the paragraph. The insert() function always returns the position after the inserted text, so pos is always incremented.
Please note, that for each open SPAN object the closing object must be on the same paragraph. If you need a linebreak you can use the code Char(10) to create a soft line break.
Usually SPAN objects are not visible. They can be made visible using the flag wpShowSPANCodes in property Formatoptions. The display is controlled by property SPANObjectTextAttr, the text can be changed using SPANObjectTextAttr.CodeOpeningText and SPANObjectTextAttr.CodeClosingText (%Y inserts the StyleName).
7) Working with the Character Attributes (Line 4)
In this demo we wanted to show how to use the low level methods. You can of course also create text using the procedure InputString and modify the current writing mode using the interface 'CurrAttr' - the demo GridMode uses the InputString technology. But this demo creates the text a bit differently. Please don't read on if you find this confusing. Using the AttrHelper interface ist usually much easier.
First we need a buffer for our character attributes: ca : TWPCharAttr;
Then we create the paragraph: par := WPRichText1.ActiveText.AppendPar;
The buffer is initialized with FillChar(ca, SizeOf(ca), 0); If you are using Delphi 8 you can define another emptyca : TWPCharAttr and assign it to clear ca.
Now we fill the paragraph by appending text.
pos := par.Insert(0,'4) DEFAULT "FIRST" ',0); par.RTFProps.AttrInterface.SetCharStyles(ca, WPSTY_ITALIC, WPSTY_ITALIC); par.RTFProps.AttrInterface.SetFontSize(ca, 12); pos := par.Insert(pos,'12ptITALIC ',ca);
"pos" is an integer value which is the index into the paragraph. The insert() function always returns the position after the inserted text, so pos is always incremented.
The lines with par.RTFProps.AttrInterface.... are used to modify ca - which in the end will be used as parameter to insert().
AttrInterface is an object of class TWPCharAttrInterface. This class is not used to store attributes but to modify buffer variables of type TWPCharAttr!
8) The complete source of the "Init Text" procedure
var par: TParagraph; sty: TWPTextStyle; pos: Integer; spanobj_open, spanobj_close: TWPTextObj; ca: TWPCharAttr; begin WPRichText1.DefaultAttr.SetFontName(ComboBox1.Text); WPRichText1.DefaultAttr.SetFontSize(WPValueEdit2.Value / 20);
WPRichText1.Clear; // Set BODY WPRichText1.ActiveText := WPRichText1.BodyText; // ---------------------------------------------------- FIRST LINE ----------- // We use the DefaultAttr ---------------------------------------------------- par := WPRichText1.ActiveText.AppendPar; par.SetText('1) This line uses no style - It uses WPRichText1.DefaultAttr !'); // ---------------------------------------------------- SECOND LINE ---------- // We use the default Style for the complete paragraph ----------------------- // Creates Style sty := WPRichText1.ParStyles.AddStyle('FIRST'); // Create Paragraph par := WPRichText1.ActiveText.AppendPar; par.SetText('2) This line uses the FIRST style'); // Assign Style par.ABaseStyle := sty; // Set Props sty.ASetAddCharStyle(WPSTY_BOLD); sty.ASetFontName('Verdana'); sty.ASet(WPAT_CharFontSize, 13 * 100); // ---------------------------------------------------- THIRD LINE ----------- // We embedd a SPAN style ---------------------------------------------------- // Creates Style sty := WPRichText1.ParStyles.AddStyle('SECOND'); // Set Props sty.ASetAddCharStyle(WPSTY_ITALIC); sty.ASet(WPAT_CharFontSize, 10 * 100); // Create Paragraph par := WPRichText1.ActiveText.AppendPar; pos := par.Insert(0, '3) SECOND STYLE - except for ', 0); spanobj_open := par.InsertNewObject(pos, wpobjSPANStyle, true, false); spanobj_open.StyleName := 'FIRST'; inc(pos); pos := par.Insert(pos, '<SPAN "FIRST">', 0); spanobj_close := par.InsertNewObject(pos, wpobjSPANStyle, true, true); spanobj_close.SetTag(spanobj_open.NewTag); //<-- tags are used to link start with end! inc(pos); par.Insert(pos, ' - END', 0); par.ABaseStyleName := 'SECOND'; // ----------------------------------------------------- 4th LINE ------------ // We use character attributes ----------------------------------------------- // 'ca' is used as buffer to create a char attribute par := WPRichText1.ActiveText.AppendPar;
FillChar(ca, SizeOf(ca), 0); pos := par.Insert(0, '4) DEFAULT "FIRST" ', 0); par.RTFProps.AttrInterface.SetCharStyles(ca, WPSTY_ITALIC, WPSTY_ITALIC); par.RTFProps.AttrInterface.SetFontSize(ca, 12); pos := par.Insert(pos, '12ptITALIC ', ca);
FillChar(ca, SizeOf(ca), 0); par.RTFProps.AttrInterface.SetFontName(ca, 'Courier New'); par.RTFProps.AttrInterface.SetFontSize(ca, 10); par.RTFProps.AttrInterface.SetColor(ca, clGreen); pos := par.Insert(pos, '10ptGreenCourier ', ca);
FillChar(ca, SizeOf(ca), 0); par.RTFProps.AttrInterface.SetColor(ca, clBlue); par.Insert(pos, 'blue text', ca);
// Assign the FIRST Style par.ABaseStyleName := 'FIRST';
// ----------------------------------------------------- last LINE -------- // We use a character style ----------------------------------------------- // 'ca' is used as buffer to create a char attribute par := WPRichText1.ActiveText.AppendPar;
FillChar(ca, SizeOf(ca), 0); pos := par.Insert(0, '5) default ', 0); par.RTFProps.AttrInterface.SetCharStyleSheet(ca, par.RTFProps.ParStyles.GetID('FIRST')); pos := par.Insert(pos, 'with chararacter-style FIRST', ca); par.Insert(pos, ' default (RTF does not preserve character styles)', 0); end;
9) Working with CSS
CSS means Cascading Style Sheet and is used to store any kind of paragraph and character attributes in HTML files. WPTools 5 was created keeping in mind the philosophy of both, CSS and RTF to provide the developer the best of both worlds.
[>>] WPTools' TWPTextStyle class has the ability to dump its properties (to be exact: only the properties supported by CSS) as a CSS string:
var sty : TWPTextStyle; begin sty := WPRichText1.ParStyles.FindTextStyle('FIRST'); if sty<>nil then CSS1.text := sty.AGet_CSS(true,false,true); end;
[<<] To load a CSS string back into a TWPTextStyle you can use the TWPCSSParserStyleWP which is implemented in unit WPIOCSS:
var sty : TWPTextStyle; parser : TWPCSSParserStyleWP; begin sty := WPRichText1.ParStyles.FindTextStyle('FIRST'); if sty<>nil then begin parser := TWPCSSParserStyleWP.Create; try parser.AsString := CSS1.text; parser.ApplyToStyle(sty); WPRichText1.ReformatAll(true); // Initialize all because we changed the font WPRichText1.Repaint; finally parser.Free; end; end; end;
Please note that the TParagraph inherits from TWPTextStyle - so the above techniques can be also used for any paragraph object!
10) Working with WPCSS
WPTools can work with string representation of property settings. Theses are called WPCSS strings due to their similarity to CSS.
To read a WPCSS string use
function TWPTextStyle.AGetWPSS( Names, CharAttr, TabAttr: Boolean; OnlyUsePTag: Boolean = FALSE; Abbreviated: Boolean = FALSE): AnsiString;
To write it use
procedure TWPTextStyle.ASetWPSS( const WPCSSString: AnsiString; Merge: Boolean = false; Abbreviated: Boolean = FALSE);
If OnlyUsePTag is set to TRUE no style names are written. You should not use this feature if you want to store the created string. It will be invalid the next time the text is created.
If Abbreviated is TRUE the short form for the property names will be used.
|