illustrator CS4: How do I set a layer to any color?

G’day scripters.

I’d like to set an entire layer to a color other than black in illustrator. I’ve tried GUI scripting as below, to no avail.

Can anyone tell me how to do this please?

Regards

Santa


-- The script

tell application "Adobe Illustrator"
	activate
	tell document 1
		tell application "System Events" to tell process "Adobe Illustrator"
			keystroke "a" using command down
			click at {115, 69} --
			set temp to the result
			click temp
			click at {90, 88}
			set temp to the result
			click temp
		end tell
	end tell
end tell



gives...

tell application "Adobe Illustrator"
	activate
end tell
tell application "System Events"
	keystroke "a" using command down
	click process "Adobe Illustrator" at {115, 69} --<-- the color box
		--> UI element 1 of UI element 1 of window 5 of application process "Adobe Illustrator"
	click UI element 1 of UI element 1 of window 5 of application process "Adobe Illustrator"
		--> missing value
	click process "Adobe Illustrator" at {90, 88} --<-- position of 'red'
		--> missing value
	click missing value
end tell

Model: early 2009 24" iMac
Browser: Safari 531.9
Operating System: Mac OS X (10.6)

With help, came up with this, and it’s quite fast. Posted for posterity.

ColorStore comes from the color picker.



on SetLayerColor()
	tell application "Adobe Illustrator"
		activate
		try
			tell document 1
				set visible of layer "Our Layer" to false
				set MyItems to last layer
				my IterateLoop(MyItems, item 1 of ColorStore, item 2 of ColorStore, item 3 of ColorStore)
				set visible of layer "Our Layer" to true
			end tell
		end try
	end tell
end SetLayerColor

on IterateLoop(TheLoop, RR, GG, BB)
	tell application "Adobe Illustrator"
		set MyItems to every page item of TheLoop
		repeat with i in MyItems
			set myObjectClass to class of i
			if myObjectClass = group item then
				my IterateLoop(i, RR, GG, BB)
			else
				
				if myObjectClass = compound path item then
					set fill color of path items of i to {red:RR, green:GG, blue:BB}
					--set stroke color of path items of i to {red:RR, green:GG, blue:BB} --sets strokes to default 20
				else if myObjectClass = path item then
					set fill color of i to {red:RR, green:GG, blue:BB}
					--set stroke color of i to {red:RR, green:GG, blue:BB}  --<-- sets strokes to default 20 as well
				end if
			end if
		end repeat
	end tell
end IterateLoop

G’day

With help from the Adobe forums, I’ve fixed the stroke command, and the amended code, along with the colorwell code, is…


if name of theObject = "theColorWell" and not LayerReDraw then -- and not LayerReDraw 
		set LayerReDraw to true
		set ColorStoreTemp to color of color panel
		set item 1 of ColorStore to ((item 1 of ColorStoreTemp) / 65535) * 255
		set item 2 of ColorStore to ((item 2 of ColorStoreTemp) / 65535) * 255
		set item 3 of ColorStore to ((item 3 of ColorStoreTemp) / 65535) * 255
		my SetLayerColor("Comparison Layer")
		set LayerReDraw to false
	end if
	if name of theObject = "theColorWell2" and not LayerReDraw then -- and not LayerReDraw 
		set LayerReDraw to true
		set ColorStoreTemp to color of color panel
		set item 1 of ColorStore2 to ((item 1 of ColorStoreTemp) / 65535) * 255
		set item 2 of ColorStore2 to ((item 2 of ColorStoreTemp) / 65535) * 255
		set item 3 of ColorStore2 to ((item 3 of ColorStoreTemp) / 65535) * 255
		my SetLayerColor("Check Layer")
	        set LayerReDraw to false
	end if
	
on SetLayerColor(theLayer)
	set slidervalue to the content of slider "LayerTransparency" of window 1
	tell application "Adobe Illustrator"
		activate
		try
			tell document 1
				if not (exists layer "Original layer") then set name of last layer to "Original layer"
				set tempFlag to visible of layer "Original layer"
				set visible of layer "Original layer" to false
				set visible of layer theLayer to true
				set MyItems to layer theLayer
				if theLayer = "Comparison Layer" then
					my IterateLoop(MyItems, item 1 of ColorStore, item 2 of ColorStore, item 3 of ColorStore)
				else
					my IterateLoop(MyItems, item 1 of ColorStore2, item 2 of ColorStore2, item 3 of ColorStore2)
				end if
				set opacity of layer "Comparison Layer" to slidervalue
				set visible of layer "Original layer" to tempFlag
			end tell
		end try
	end tell
end SetLayerColor

on IterateLoop(TheLoop, RR, GG, BB)
	tell application "Adobe Illustrator"
		set MyItems to every page item of TheLoop
		set mynewcolor to {red:RR, green:GG, blue:BB}
		repeat with i in MyItems
			try
				set myObjectClass to class of i
				if myObjectClass = group item then
					my IterateLoop(i, RR, GG, BB)
				else
					
					if myObjectClass = compound path item then
						repeat with j from 1 to (count of path items of i)
							if (true is in filled of path item j of i) then set fill color of path item j of i to mynewcolor
							if (true is in stroked of path item j of i) then set stroke color of path item j of i to mynewcolor
						end repeat
					else if myObjectClass = path item then
						if (true is in filled of i) then set fill color of i to mynewcolor
						if (true is in stroked of i) then set stroke color of i to mynewcolor
					end if
				end if
			on error errmsg
				display dialog errmsg
			end try
		end repeat
	end tell
end IterateLoop

This allows you to get the color that is user by the layer

tell application “Adobe Illustrator”
set myProps to the color of layer 1 of the front document
log myProps
end tell

Info is returned as an RGB object and can also be set. This is the color that the layer uses in the Layers panel. Is that what you want?

G’day Zav.

Unfortunately it’s more complicated than that.

Rather than just set the color of a Layer, I need to color every stroke and fill.

You normally do this by Selecting All and choose a color from the color palette. This is very difficult to emulate with the GUI, and in objects with 50,000 plus page items can take a whole day to color, impossibly long, though it’s fast with about 1000 items.

Thanks anyway

Regards

Santa

Oh, OK. No problem.

The deal is that as far as I could find, there is no easy parent/child relationship between layers and their contents. As far as I know you can’t say “give me all the elements that are in this layer”.

What I was able to do was walk through every “page item” and check its container. If that container is the desired layer, than add that page item to an array.

When done, walk all the elements in the array and check their class or their properties. If their properties have stroke and fill then you can set the stroke and fill of each item.

That should do it and be pretty fast.

Is that how you are already trying to do it?

But then again, I could be really wrong:

tell application “Adobe Illustrator”
set myList to every page item in layer 1 of document 1
end tell

{path item 1 of layer 1 of document 1 of application “Adobe Illustrator”, path item 2 of layer 1 of document 1 of application “Adobe Illustrator”, path item 3 of layer 1 of document 1 of application “Adobe Illustrator”}

G’day again Zav

my latest script is below. Using a counter instead of ‘repeat with i in Page items’ speeds things up considerably, as does breaking the loop into ‘sections’ of 400 items.

However, documents of 50,000 page items (and we get a few of those) are still way too slow unless we use the color picker with ‘Command a’.


on CheckSize()
	tell application "Adobe Illustrator"
		tell document 1
			set theTotal to (count of page items) div (count of layers)
		end tell
		return {(theTotal > 4000), theTotal}
	end tell
end CheckSize

on setUpLayerColor(theLayer)
	set {overSize, theSize} to my CheckSize()
	if overSize then
		activate
		if theSize < 8000 then
			tell application "Finder"
				display dialog "Are you sure you want to color the '" & theLayer & "' this way?" & ¬
					return & "It appears to be " & theSize & " page items in size." & return & ¬
					"OR, use Illustrators Color Picker." buttons {"Cancel", "Use Picker", "I'm sure"}
			end tell
			set temp to button returned of result
			if temp = "I'm sure" then my SetLayerColor(theLayer)
			if temp = "Use Picker" then
				tell application "Adobe Illustrator"
					activate
					tell document 1
						repeat with x from 1 to count of layers
							set the locked of layer x to false
							set the visible of layer x to false
						end repeat
						set the visible of layer theLayer to true
					end tell
				end tell
				tell application "System Events" to tell process "Adobe Illustrator"
					keystroke "a" using {command down}
					tell application "Finder"
						activate
						display dialog "I've 'Selected All' on the layer, so please pick a color from the Illustrator color picker." buttons {"OK"}
					end tell
					tell application "Adobe Illustrator"
						activate
						tell document 1
							set the locked of layer "Original Layer" to true
						end tell
					end tell
				end tell
			end if
		else
			tell application "Adobe Illustrator"
				activate
				tell document 1
					repeat with x from 1 to count of layers
						set the locked of layer x to false
						set the visible of layer x to false
					end repeat
					set the visible of layer theLayer to true
				end tell
			end tell
			tell application "System Events" to tell process "Adobe Illustrator"
				keystroke "a" using {command down}
			end tell
			tell application "Finder"
				activate
				display dialog "The '" & theLayer & "' is too large at " & theSize & " page items in size." & return & ¬
					"I've 'Selected All' on the layer, so please pick a color from the Illustrator color picker." buttons {"OK"}
				tell application "Adobe Illustrator"
					activate
					tell document 1
						set the locked of layer "Original Layer" to true
					end tell
				end tell
			end tell
		end if
	else
		my SetLayerColor(theLayer)
	end if
end setUpLayerColor

on SetLayerColor(theLayer)
	set slidervalue to the content of slider "LayerTransparency" of window 1
	tell application "Adobe Illustrator"
		activate
		try
			tell document 1
				if not (exists layer "Original layer") then set name of last layer to "Original layer"
				set tempFlag to visible of layer "Original layer"
				set visible of layer "Original layer" to false
				set visible of layer theLayer to true
				set MyItems to layer theLayer
				set StoreTempLocked to locked of layer theLayer
				set locked of layer theLayer to false
				if theLayer = "Working Layer" then
					my IterateLoop(MyItems, item 1 of ColorStore, item 2 of ColorStore, item 3 of ColorStore)
				else
					my IterateLoop(MyItems, item 1 of ColorStore2, item 2 of ColorStore2, item 3 of ColorStore2)
				end if
				set locked of layer theLayer to StoreTempLocked
				set opacity of layer "Working Layer" to slidervalue
				set visible of layer "Original layer" to tempFlag
			end tell
		end try
	end tell
end SetLayerColor

on IterateLoop(TheLoop, RR, GG, BB)
	tell application "Adobe Illustrator"
		set MyItems to every page item of TheLoop
		set mynewcolor to {red:RR, green:GG, blue:BB}
		with timeout of 3600 seconds
			set TheCount to count of MyItems
			repeat with x from 1 to TheCount by 400
				set y to x + 400
				if y > TheCount then set y to TheCount
				set myitems2 to items x thru y of MyItems
				repeat with yy from 1 to (y - x + 1)
					set i to item yy of myitems2
					try
						set myObjectClass to class of i
						if myObjectClass = group item then
							my IterateLoop(i, RR, GG, BB)
						else
							
							if myObjectClass = compound path item then
								repeat with j from 1 to (count of path items of i)
									if (true is in filled of path item j of i) then set fill color of path item j of i to mynewcolor
									if (true is in stroked of path item j of i) then set stroke color of path item j of i to mynewcolor
								end repeat
							else if myObjectClass = path item then
								if (true is in filled of i) then set fill color of i to mynewcolor
								if (true is in stroked of i) then set stroke color of i to mynewcolor
							end if
						end if
					on error errmsg
						display dialog errmsg
					end try
				end repeat
			end repeat
		end timeout
	end tell
end IterateLoop

Damn, and it just gets easier every second.

tell application “Adobe Illustrator”
set the stroke width of every page item in layer 1 of document 1 to 2
end tell

Yes Zav, but you’re not testing for conditions. Try this…


tell application "Adobe Illustrator"
	set the color of every page item in layer 1 of document 1 whose stroked = true to {red:255, green:255, blue:255}
end tell

How about this:

tell application “Adobe Illustrator”
set the stroke width of every page item in layer 1 of document 1 to 2

set myColor to {class:RGB color info, red:0, green:255, blue:0}
set the fill color of every page item in layer 1 of document 1 to myColor
set the stroke color of every page item in layer 1 of document 1 to myColor

end tell

I tested it on a document with 3 rectangles in layer 1 and it was pretty fast.

I just created over 20,000 rects in layer 1 and running it still took less than 20 seconds on 24 inch Intel iMac.

Browser: Safari 531.21.10
Operating System: Mac OS X (10.6)

I didn’t know that you needed to check for conditions.

You could wrap the one liner in a try statement, or if that won’t work, the speed hog is in the repeat loop.

What you need to do is not this:

repeat with x from 1 to count of layers

What that does is count the layers every time you iterate through the loop. Do this instead:

set myLayers to count of layers
repeat with x from 1 to myLayers

You do this later on in your code in IterateLoop.

Just make sure to remove the count from the repeat conditions and reference it as a variable with an integer value. It should speed things up a bit.

Hope this helped, but I’ve got to get back to my code.

Cheers,

Thanks Zav, and good luck with your coding.

Addressing the layers is simple, simply hide the ones you don’t want to address, which is what I’ve done.

Colouring a stroke that is not ‘Stroked = true’ sets the default width of the stroke to 20, so it has to be tested before coloring.

Regards

Santa