Reply to topic  [ 9 posts ] 
Toggle Paragraph Spacing... 
Author Message

Joined: 2010-02-22 15:06:48
Posts: 98
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


2016-09-12 14:17:51
Profile
User avatar

Joined: 2007-02-07 00:58:12
Posts: 876
Location: Japan
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:
$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:
$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:
$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:
$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:
$sel = TextSelection.active
$attrs = $sel.displayTypingAttributes
$style = $attrs.paragraphStyle

Now you can ask for the space before attached to the style:
Code:
$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:
$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


2016-09-12 18:08:52
Profile

Joined: 2010-02-22 15:06:48
Posts: 98
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


2016-09-12 19:48:01
Profile

Joined: 2012-12-19 05:02:52
Posts: 224
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?

Quote:
$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


2016-09-13 05:47:24
Profile
User avatar

Joined: 2007-02-07 00:58:12
Posts: 876
Location: Japan
Þ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:
$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:
$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:
$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


2016-09-13 08:10:22
Profile
User avatar

Joined: 2007-02-07 00:58:12
Posts: 876
Location: Japan
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:
$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:
$reg = Registry.userRegistry
$numberBefore = $reg.loadValueWithName 'name.thorvarthur.toggleMacro.numberBefore'
$sel = TextSelection.active



Hope this helps.

_________________
philip


2016-09-13 08:49:58
Profile

Joined: 2012-12-19 05:02:52
Posts: 224
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
Quote:
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


2016-09-14 04:30:14
Profile

Joined: 2007-03-28 07:30:34
Posts: 139
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.


2016-09-15 11:45:44
Profile

Joined: 2012-12-19 05:02:52
Posts: 224
Thank you very much credneb.


2016-09-15 15:37:28
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 9 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software