Toggle Paragraph Spacing...

Get help using and writing Nisus Writer Pro macros.
Post Reply
goldste4
Posts: 98
Joined: 2010-02-22 15:06:48

Toggle Paragraph Spacing...

Post by goldste4 » 2016-09-12 14:17:51

Hello All,

I need a macro that can toggle the paragraph spacing before in the paragraph where the caret is. E.g, if the paragraph spacing before is currently set to 0 pt, running the macro will set it to 14 pt and vice versa. The part I cannot quite figure out is how to read the current "paragraph spacing before" state to then toggle it: it is just my ignorance of object oriented programming that is standing in the way, I must admit.

As a bonus, it would be great to be able to read the line spacing of the "normal" paragraph style and set the paragraph spacing value relative to that rather than hard code in 14 pt paragraph spacing.

Any help would be much appreciated!

Much thanks in advance,
Josh

User avatar
phspaelti
Posts: 912
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Toggle Paragraph Spacing...

Post by phspaelti » 2016-09-12 18:08:52

Hi Josh,

working with the object model means that you will need an object to get the attributes. There are three objects which can return attribute information.
First the Text object will have attribute information for any location inside it. Second the TextSelection object will have attribute information for the all the text that is part of it, but in addition will have attributes that will apply if you start typing at that location. Third the Style object will have attribute information that is part of its definition, including attributes information that it may inherit from another style. So to get anywhere we will need one of these objects. Since you want to the information for the current selection let's start with that.

Code: Select all

$sel = TextSelection.active
So this command retrieves the current ("active") text selection and returns it as "$sel". You can now ask for the attributes that will apply when you type at that location like this:

Code: Select all

$attrs = $sel.typingAttributes
And within those attributes we can ask for the paragraph spacing before, and set things accordingly. So a complete macro will look like this:

Code: Select all

$sel = TextSelection.active
$attrs = $sel.typingAttributes
if $attrs.paragraphSpacingBefore == 14
	Set Paragraph Spacing Before 0
else
	Set Paragraph Spacing Before 14
end
Now there is one problem with the above macro. Let's assume that all your text has the style "MyStyle" applied and this style includes as part of its definition "Paragraph Spacing Before 14". Running the macro will have zero effect. Why is that? Well attributes come in two parts: first there are the attributes that have been directly applied to your text, but then there are the attributes that are the result of inheritance from other places. When you ask for the typingAttributes you get only the attributes that are actively applied. Since in our scenario the 14pt spacing is part of the style, it is not applied. The macro will decide that the space before attribute is not set to 14 and try to apply it, and NIsus will resolve this by deciding that the spacing is already applied by the style and is redundant, and so it will 'eat it'. The paragraph will continue to have no space before attribute, and will therefore continue to display the 14pt spacing before set by the style.

To solve this Nisus has a second attribute returning command, with an added "display". Using this type of command ensures that you always get a value:

Code: Select all

$attrs = $sel.displayTypingAttributes
If you change the command in the above macro you will get a macro that consistently toggles the spacing between 0 and 14pts.

But this isn't really what you are looking for. What you want is spacing before relative to the current style. So the first thing we need is the current style:

Code: Select all

$sel = TextSelection.active
$attrs = $sel.displayTypingAttributes
$style = $attrs.paragraphStyle
Now you can ask for the space before attached to the style:

Code: Select all

$spaceBefore = $style.displayAttributes.paragraphSpacingBefore
Note that I am again using "display" attributes to ensure I get a value. Also I am stringing commands together (get the "paragraph spacing before" from the "display attributes"), just to save time/lines of codes/variables. You can do it in two steps, if you prefer, just watch the variable names!
We can now ask if the current space before is equal to that of the style, and if yes increase it by 14pts, otherwise set it back. So the whole macro might look like this:

Code: Select all

$sel = TextSelection.active
$attrs = $sel.displayTypingAttributes
$style = $attrs.paragraphStyle
$spaceBefore = $style.displayAttributes.paragraphSpacingBefore
if $attrs.paragraphSpacingBefore == $spaceBefore
	$spaceBefore += 14
end
Set Paragraph Spacing Before $spaceBefore
Hope all this is clear.
philip

goldste4
Posts: 98
Joined: 2010-02-22 15:06:48

Re: Toggle Paragraph Spacing...

Post by goldste4 » 2016-09-12 19:48:01

Hi Philip,

Thank you very much — that was an exceptionally clear and thoughtful explanation! I can now see what I was doing wrong trying to read the attributes, and where I would likely have further gone wrong by not distinguishing the 'display' and non-display TypingAttributes.

The macro works great and will be very helpful for me.

All the best,
Josh

Þorvarður
Posts: 248
Joined: 2012-12-19 05:02:52

Re: Toggle Paragraph Spacing...

Post by Þorvarður » 2016-09-13 05:47:24

Hi Philip,

Assuming we want the space before to be 14, and sometimes something else. How can we do that?
"Prompt Input" looks like a good way to go, but how can we turn a new input entered by the user into a global variable so that it will stick?
$numberBefore = Prompt Input 'Enter space before …', '', '', '14'
$sel = TextSelection.active
$attrs = $sel.displayTypingAttributes
$style = $attrs.paragraphStyle
$spaceBefore = $style.displayAttributes.paragraphSpacingBefore
if $attrs.paragraphSpacingBefore == $spaceBefore
$spaceBefore += $numberBefore
end
Set Paragraph Spacing Before $spaceBefore
If I enter 8, I would like to save that number somehow, so that next time the macro is run, 8 will come up instead of 14.

My guess is that .saveValueWithName value, name could perhaps be used, but the Registry Examples in the Macro Language Reference are not very helpful.


Þorvarður

User avatar
phspaelti
Posts: 912
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Toggle Paragraph Spacing...

Post by phspaelti » 2016-09-13 08:10:22

Þorvarður wrote:My guess is that .saveValueWithName value, name could perhaps be used, but the Registry Examples in the Macro Language Reference are not very helpful.
Actually I don't think there is anything wrong with the examples, it's the whole registry construct that's the problem :P

Anyhow you should probably start by deciding on the address where you want to store the info. The name can really be anything you want, but following the (updated :D ) instructions in the reference we might choose for your macro variable: name.thorvarthur.toggleMacro.spaceBefore.

Okay, so that's where we save the variable.

Now the second thing we need to decide is the storage type: user, application, or macro? But actually this decides itself. I assume you want this variable to be around from one start of Nisus to the next. So user it is.

Okay now the first step is to define a registry variable. We need to give this a name too. Why? Beats me! What name should you choose? Anything will do, the name doesn't seem to have any function. What's more, is that even though we have to create such a variable, we can really only create one. So it's probably be best to always use the same one. The reference suggests $registry, but thats too long for me. I use $reg.

Finally the reference introduces yet another variable (with yet another name :roll: ) where they store the name we decided on first (name.thorvarthur.toggleMacro.spaceBefore).
That's just too many names for me. And it increases the lines of code we need for this procedure. So I prefer the following:

Code: Select all

$reg = Registry.userRegistry
$reg.saveValueWithName $spaceBefore, 'name.thorvarthur.toggleMacro.spaceBefore'
Later when you want to retrieve this variable again you will use the following code:

Code: Select all

$reg = Registry.userRegistry
$spaceBefore = $reg.loadValueWithName 'name.thorvarthur.toggleMacro.spaceBefore'
To keep your sanity about this process, I strongly recommend that you vary this code as little as possible. In particular I recommend always using the same name for the variable in the storage address that you also use in the macro itself ($spaceBefore, …spaceBefore). Then keep the macro name in the storage address with a distinctive name that makes it clear which macro it goes with.

Finally, if you want to save and or load several variables you of course only need to create the $reg variable once in the macro. So it might be best to do that at the very beginning of the macro.

And now we apply this to your macro. (Actually you want to save $numberBefore not $spaceBefore.)

Code: Select all

$reg = Registry.userRegistry
$numberBefore = $reg.loadValueWithName 'name.thorvarthur.toggleMacro.numberBefore'
$numberBefore = Prompt Input 'Enter space before …', '', '', $numberBefore
$reg.saveValueWithName $numberBefore, 'name.thorvarthur.toggleMacro.numberBefore'
$sel = TextSelection.active
$attrs = $sel.displayTypingAttributes
$style = $attrs.paragraphStyle
$spaceBefore = $style.displayAttributes.paragraphSpacingBefore
if $attrs.paragraphSpacingBefore == $spaceBefore
$spaceBefore += $numberBefore
end
Set Paragraph Spacing Before $spaceBefore
philip

User avatar
phspaelti
Posts: 912
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Toggle Paragraph Spacing...

Post by phspaelti » 2016-09-13 08:49:58

One more thing Þorvarður,
just in case it wasn't clear, now that the variable is a global variable, you can detach the input from the toggle macro. You will then use the input macro only when you want to change the value of the variable.
To get this to work you will have to repeat the load instruction in the toggle macro.

This is the input macro:

Code: Select all

$reg = Registry.userRegistry
$numberBefore = $reg.loadValueWithName 'name.thorvarthur.toggleMacro.numberBefore'
$numberBefore = Prompt Input 'Enter space before …', '', '', $numberBefore
$reg.saveValueWithName $numberBefore, 'name.thorvarthur.toggleMacro.numberBefore'
The toggle macro will now start like this:

Code: Select all

$reg = Registry.userRegistry
$numberBefore = $reg.loadValueWithName 'name.thorvarthur.toggleMacro.numberBefore'
$sel = TextSelection.active
…
Hope this helps.
philip

Þorvarður
Posts: 248
Joined: 2012-12-19 05:02:52

Re: Toggle Paragraph Spacing...

Post by Þorvarður » 2016-09-14 04:30:14

phspaelti wrote:Hope this helps.
Yes, this will keep me busy for the next three months trying to understand how this magic works. :lol:

You said
Now the second thing we need to decide is the storage type: user, application, or macro?
You are right, in this particular macro the variable should be around from one start of Nisus to the next.

Creating global variables in Nisus Classic was easy. I remember that one global variable could be loaded when the program was launched. Was that the same feature as storage type application in Nisus Writer Pro now?

Does storage type macro mean, that it will only exist as long as the macro is run? I'm just guessing here, because where in the Macro Language Reference are these three storage types explained? :?


Þorvarður

credneb
Posts: 146
Joined: 2007-03-28 07:30:34

Re: Toggle Paragraph Spacing...

Post by credneb » 2016-09-15 11:45:44

Hi, Þorvarður.

In the macro language reference go to
Objects : Registry Object: Registry Type Commands

or faster, search for "user registry" and you'll go straight there.

Þorvarður
Posts: 248
Joined: 2012-12-19 05:02:52

Re: Toggle Paragraph Spacing...

Post by Þorvarður » 2016-09-15 15:37:28

Thank you very much credneb.

Post Reply