Styles: rvstkParaText vs rvstkPara vs rvstkText

General TRichView support forum. Please post your questions here
Post Reply
VicFan
Posts: 11
Joined: Sun Jul 28, 2019 8:34 pm

Styles: rvstkParaText vs rvstkPara vs rvstkText

Post by VicFan » Sat Aug 17, 2019 12:02 am

I am struggling to understand where to use these constants. It is obvious Para vs Text, but it seems like "Normal" template style would be both (i.e., that should be ParaText). However, I have gotten "wrong kind of StyleTemplate parent" run time errors if I try to derive a text style from a Normal template (e.g., uncomment the line in the code below).

Also, can you tell me what is wrong with filling the style template this way. I want to do something like this to allow dynamically setting it based on user's settings, so the easiest thing to do in my situation is build it all in code. The problem here is that counts never get any larger than zero and the resulting display of the line printed (on my test machine turns out red, rather than either black or blue, the only colors I specified).

If it is not too difficult, can you fix this small sample?

Code: Select all

int __fastcall getTextStyleIdByName(TRichView * rv, UnicodeString styleName, int defaultVal=-1) {
	int rtnVal = defaultVal;
	TRVStyle * Style = rv->Style;
	for (int i = 0; i < Style->TextStyles->Count ; i++) {           // Count turns out to be zero
		if (Style->TextStyles->Items[i]->StyleName == styleName) {
			rtnVal = i;
			break;
		}
	}
	return rtnVal;
}

int __fastcall getParaStyleIdByName(TRichView * rv, UnicodeString styleName, int defaultVal=-1) {
	int rtnVal = defaultVal;
	TRVStyle * Style = rv->Style;
	for (int i = 0; i < Style->ParaStyles->Count ; i++) {          // Counts turns out to be zero
		if (Style->ParaStyles->Items[i]->StyleName == styleName) {
			rtnVal = i;
			break;
		}
	}
	return rtnVal;
}

void __fastcall TForm1::btnDisplayClick(TObject *Sender)
{
	TRVStyle * Style = rv->Style;
	TRVStyleTemplate * Template;
	TRVSTParaInfo * ParaStyle;
	TRVSTFontInfo * TextStyle;
	TRVTabInfo* Tab;
	int styleNormal;

	UnicodeString font = "Arial";
	int fontSize = 12;

	Style->TextStyles->Clear();
	Style->ParaStyles->Clear();
	Style->ListStyles->Clear();

	Template = Style->StyleTemplates->Add();
	Template->Kind = rvstkParaText;
	Template->Name = "Normal";
	TextStyle = Template->TextStyle;
	TextStyle->FontName = font;
	TextStyle->SizeDouble = fontSize * 2;
	TextStyle->Color = clBlack;
	ParaStyle = Template->ParaStyle;
	ParaStyle->Alignment = rvaLeft;
	ParaStyle->SpaceBefore = 0;
	ParaStyle->SpaceAfter = 0;
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(0.4, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(0.8, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(1.2, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(1.6, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(2.0, rvuInches);

	styleNormal = Template->Id;

	Template = Style->StyleTemplates->Add();
	//Template->Kind = rvstkText;       // Causes "Wrong kind of StyleTemplate parent" error
	Template->ParentId = styleNormal;
	Template->NextId = styleNormal;
	Template->Name = "AAA";
	TextStyle = Template->TextStyle;
	TextStyle->Style << fsBold;
	TextStyle->Color = clBlue;

	rv->AddNL("Hi there", getTextStyleIdByName(rv, "AAA"), getParaStyleIdByName(rv, "Normal"));
	rv->FormatTail();
}

Sergey Tkachenko
Site Admin
Posts: 14551
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Styles: rvstkParaText vs rvstkPara vs rvstkText

Post by Sergey Tkachenko » Sat Aug 17, 2019 1:09 pm

I tried to explain StyleTemplates here: https://www.trichview.com/forums/viewto ... f=3&t=8804

In your code fragment, I can see the following problems:

1) Your getTextStyleIdByName() and getParaStyleIdByName() search in the collections TextStyles and ParaStyles. But you add items in StyleTemplates.
Please ignore StyleName property of TextStyles and ParaStyles. If you use StyleTemplates, it's better to leave TextStyles and ParaStyles unnamed. Only StyleTemplates should have names.

2) When constructing a StyleTemplate, you need to list all properties that you defined in ValidTextProperties and ValidParaProperties.
For example, for your "Normal" StyleTemplate, ValidTextProperties must contain rvfiFontName, rvfiSize, rvfiColor; ValidParaProperties must contain rvpiAlignment, rvpiSpaceBefore, rvpiSpaceAfter, rvpiTabs.

3) Parent of rvstkText StyleTemplate may be only another rvstkText StyleTemplate.

4) 1) At least one text and paragraph style must exist. But you deleted all of them. You need to add at least one ParaStyle and TextStyle, and link them to StyleTemplates using StyleTemplateId and ParaStyleTemplateId properties. Note that linking itself does not affect properties of ParaStyle and TextStyle, you need to call ApplyToParaStyle()/ApplyToTextStyle() to modify them.

Sergey Tkachenko
Site Admin
Posts: 14551
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Styles: rvstkParaText vs rvstkPara vs rvstkText

Post by Sergey Tkachenko » Sat Aug 17, 2019 1:12 pm

Fixed code:

Code: Select all

	TRVStyle * Style = rve->Style;
	TRVStyleTemplate * Template;
	TCustomRVParaInfo * ParaStyle;
	TCustomRVFontInfo * TextStyle;
	TRVTabInfo* Tab;

	UnicodeString font = "Arial";
	int fontSize = 12;

	// =================== Creating style templates

	Template = Style->StyleTemplates->Add();
	Template->Kind = rvstkParaText;
	Template->Name = "Normal";
	TextStyle = Template->TextStyle;
	TextStyle->FontName = font;
	TextStyle->SizeDouble = fontSize * 2;
	TextStyle->Color = clBlack;
	ParaStyle = Template->ParaStyle;
	ParaStyle->Alignment = rvaLeft;
	ParaStyle->SpaceBefore = 0;
	ParaStyle->SpaceAfter = 0;
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(0.4, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(0.8, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(1.2, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(1.6, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(2.0, rvuInches);
	Template->ValidTextProperties << rvfiFontName << rvfiSize << rvfiColor;
	Template->ValidParaProperties << rvpiAlignment << rvpiSpaceBefore
	  << rvpiSpaceAfter << rvpiTabs;

	styleNormal = Template->Id;

	Template = Style->StyleTemplates->Add();
	Template->Kind = rvstkText;
	Template->NextId = -1;
	Template->Name = "AAA";
	TextStyle = Template->TextStyle;
	TextStyle->Style << fsBold;
	TextStyle->Color = clBlue;
	Template->ValidTextProperties << rvfiBold << rvfiColor;

	// =================== Creating text and paragraph styles

	Style->TextStyles->Clear();
	Style->ParaStyles->Clear();
	Style->ListStyles->Clear();


	TRVStyleTemplate * NormalStyleTemplate = rvs->StyleTemplates->NormalStyleTemplate;
	TRVStyleTemplate * TextStyleTemplate;

	// creating a paragraph style linked to "Normal"
	ParaStyle = Style->ParaStyles->Add();
	// linking "Normal" to ParaStyle
	ParaStyle->StyleTemplateId = NormalStyleTemplate->Id;
	// changing properties of ParaStyle according to its StyleTemplate
	NormalStyleTemplate->ApplyToParaStyle(ParaStyle);

	// creating a text style that is not linked to StyleTemplate, but
	// should be used in "Normal" paragraphs
	TextStyle = Style->TextStyles->Add();
	TextStyle->ParaStyleTemplateId = NormalStyleTemplate->Id;
	// changing properties of ParaStyle accordingly
	TextStyleTemplate = NULL;
	TextStyleTemplate->ApplyToTextStyle(TextStyle, NormalStyleTemplate);

	// creating a text style that is linked to "AAA", and
	// should be used in "Normal" paragraphs
	TextStyle = Style->TextStyles->Add();
	TextStyle->ParaStyleTemplateId = NormalStyleTemplate->Id;
	// changing properties of ParaStyle accordingly
	TextStyleTemplate = rvs->StyleTemplates->FindItemByName("AAA");
	TextStyleTemplate->ApplyToTextStyle(TextStyle, NormalStyleTemplate);

	/*
	Now, we created
	ParaStyles->Items[0] linked to "Normal"
	TextStyles->Items[0] for placing in "Normal" paragraphs, not linked to ST
	TextStyles->Items[1] for placing in "Normal" paragraphs, linked to "AAA"

    */

	// sample document
	rve->Clear();
	rve->AddNL("Hi there", 0, 0); // "Normal"
	rve->AddNL("Hi there", 1, 0); // "Normal" + "AAA"
	rve->Format();

VicFan
Posts: 11
Joined: Sun Jul 28, 2019 8:34 pm

Re: Styles: rvstkParaText vs rvstkPara vs rvstkText

Post by VicFan » Sun Aug 18, 2019 12:17 am

Thank you. That was extremely helpful, but my example code didn't go far enough. Apparently paragraphs are slightly different and I have another quick question related to styles.

So I have modified your sample answer to add in a paragraph with the following requirement: there are 6 extra units above and below the "bbb" paragraph, but if two "bbb" paragraphs are immediately adjacent to each other, there is not extra space between the two. That is the idea formatting, but if there is no way to implement it (because negative units do not work), I can find some other style set-up to accomplish the requirement. For the demo code, just change the -6 to an extra 10 units between the two paragraphs if the negative units are a problem for this demo.

This will show me both how to deal with paragraph styles and how to handle one paragraph style that follows another.

So, Question #1, do styles handle negative spacing (as in the code below)?

Question #2, I want to make sure that I am properly handling one paragraph style that follows another

Question #3, how do I fix the error ("generates an error: [bcc32c Error] Unit1.cpp(314): cannot initialize a parameter of type 'Rvstyle::TCustomRVParaInfo *' with an lvalue of type 'Rvstyle::TRVStyleTemplate *' RVStyle.hpp(1393): passing argument to parameter 'AParaStyle'") when I am trying to update the paragraph style?

Code: Select all

	TRVStyle * Style = rve->Style;
	TRVStyleTemplate * Template;
	TCustomRVParaInfo * ParaStyle;
	TCustomRVFontInfo * TextStyle;
	TRVTabInfo* Tab;

	UnicodeString font = "Arial";
	int fontSize = 12;

	// =================== Creating style templates

	Template = Style->StyleTemplates->Add();
	Template->Kind = rvstkParaText;
	Template->Name = "Normal";
	TextStyle = Template->TextStyle;
	TextStyle->FontName = font;
	TextStyle->SizeDouble = fontSize * 2;
	TextStyle->Color = clBlack;
	ParaStyle = Template->ParaStyle;
	ParaStyle->Alignment = rvaLeft;
	ParaStyle->SpaceBefore = 0;
	ParaStyle->SpaceAfter = 0;
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(0.4, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(0.8, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(1.2, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(1.6, rvuInches);
	Tab = ParaStyle->Tabs->Add();
	Tab->Position = Style->RVUnitsToUnits(2.0, rvuInches);
	Template->ValidTextProperties << rvfiFontName << rvfiSize << rvfiColor;
	Template->ValidParaProperties << rvpiAlignment << rvpiSpaceBefore
	  << rvpiSpaceAfter << rvpiTabs;

	Template = Style->StyleTemplates->Add();
	Template->Kind = rvstkText;
	Template->NextId = -1;
	Template->Name = "AAA";
	TextStyle = Template->TextStyle;
	TextStyle->Style << fsBold;
	TextStyle->Color = clBlue;
	Template->ValidTextProperties << rvfiBold << rvfiColor;


	// Newly inserted test case for paragraph settings
	Template = Style->StyleTemplates->Add();
	Template->Kind = rvstkPara;
	Template->Name = "bbb";
	//Template->NextId =   ... this is done after the follow-on paragraph style is added
	ParaStyle = Template->ParaStyle;
	ParaStyle->SpaceBefore = 6;
	ParaStyle->SpaceAfter = 6;
	Template->ValidParaProperties << rvpiSpaceBefore << rvpiSpaceAfter;

	int titleParaSubscript = Style->StyleTemplates->Count - 1;
	int titleParaId = Template->Id;

	Template = Style->StyleTemplates->Add();
	Template->Kind = rvstkPara;
	Template->Name = "bbbRepeat";
	Template->ParentId = titleParaId;
	Template->NextId = Template->Id;
	ParaStyle = Template->ParaStyle;
	ParaStyle->SpaceBefore = -6;    // Question #1: does negative spacing work here?
	ParaStyle->SpaceAfter = 6;
	Template->ValidParaProperties << rvpiSpaceBefore << rvpiSpaceAfter;

	Template = Style->StyleTemplates->Items[titleParaSubscript];	//Question #2: Is this a proper way to handle one paragraph style that follows another
	Template->NextId = titleParaId;
	// End newly inserted code


	// =================== Creating text and paragraph styles

	Style->TextStyles->Clear();
	Style->ParaStyles->Clear();
	Style->ListStyles->Clear();


	TRVStyleTemplate * NormalStyleTemplate = rvs->StyleTemplates->NormalStyleTemplate;
	TRVStyleTemplate * TextStyleTemplate;

	// creating a paragraph style linked to "Normal"
	ParaStyle = Style->ParaStyles->Add();
	// linking "Normal" to ParaStyle
	ParaStyle->StyleTemplateId = NormalStyleTemplate->Id;
	// changing properties of ParaStyle according to its StyleTemplate
	NormalStyleTemplate->ApplyToParaStyle(ParaStyle);

	// Newly inserted test case for paragraph settings
	ParaStyle = Style->ParaStyles->Add();
	ParaStyle->StyleTemplateId = NormalStyleTemplate->Id;
	TRVStyleTemplate * ParaStyleTemplate = rvs->StyleTemplates->FindItemByName("bbb");
	ParaStyleTemplate->ApplyToParaStyle(ParaStyleTemplate);       // Question #3: this generates an error

	ParaStyle = Style->ParaStyles->Add();
	ParaStyle->StyleTemplateId = NormalStyleTemplate->Id;
	ParaStyleTemplate = rvs->StyleTemplates->FindItemByName("bbbRepeat");
	//ParaStyleTemplate->ApplyToParaStyle(ParaStyleTemplate);       // generates same error as Question 3 
	// End newly inserted code

	// creating a text style that is not linked to StyleTemplate, but
	// should be used in "Normal" paragraphs
	TextStyle = Style->TextStyles->Add();
	TextStyle->ParaStyleTemplateId = NormalStyleTemplate->Id;       
	// changing properties of ParaStyle accordingly
	TextStyleTemplate = NULL;
	TextStyleTemplate->ApplyToTextStyle(TextStyle, NormalStyleTemplate);

	// creating a text style that is linked to "AAA", and
	// should be used in "Normal" paragraphs
	TextStyle = Style->TextStyles->Add();
	TextStyle->ParaStyleTemplateId = NormalStyleTemplate->Id;
	// changing properties of ParaStyle accordingly
	TextStyleTemplate = rvs->StyleTemplates->FindItemByName("AAA");
	TextStyleTemplate->ApplyToTextStyle(TextStyle, NormalStyleTemplate);

	/*
	Now, we created
	ParaStyles->Items[0] linked to "Normal"
	TextStyles->Items[0] for placing in "Normal" paragraphs, not linked to ST
	TextStyles->Items[1] for placing in "Normal" paragraphs, linked to "AAA"

    */

	// sample document
	rve->Clear();
	rve->AddNL("Hi there", 0, 0); // "Normal"
	rve->AddNL("Hi there", 1, 0); // "Normal" + "AAA"
	rve->Format();

Sergey Tkachenko
Site Admin
Posts: 14551
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Styles: rvstkParaText vs rvstkPara vs rvstkText

Post by Sergey Tkachenko » Tue Aug 20, 2019 7:31 am

Sorry for the delay. I was busy fixing the web server.

Negative SpaceBefore and SpaceAfter are not allowed, sorry. When you assign a negative value to these properties, it is changed to zero.
Unfortunately, TRichView does not support the option "remove spacing between paragraphs of the same style" (planned for future).
If you need several paragraphs to be displayed in a compact way, you can use not paragraph breaks, but line breaks inside paragraphs.

When editing, you can add these breaks using Shift+Enter instead of Enter.
When using Add* methods, you can use SetAddParagraphMode.
See also AsSingleParagraph parameter of AddTextNL

Post Reply