The Omni Group
These forums are now read-only. Please visit our new forums to participate in discussion. A new account will be required to post in the new forums. For more info on the switch, see this post. Thank you!

Go Back   The Omni Group Forums > OmniGraffle > OmniGraffle Extras
FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
Annotate objects (applescript) Thread Tools Search this Thread Display Modes
Prev Previous Post   Next Post Next
I make a lot of diagrams for papers, and I found myself annotating shapes, then as the diagram changes I have to move the anotations around and it was difficult to get them correctly placed.

To solve the problem I created two scripts. The first Annotate creates an annotation for each selected object. It prompts for the position, and the margins.

The Reposition Annotation script only works on Annotations created with the annotation script. It allows the annotation to be repositioned with a different margin or on a different side of the object. Note you can select multiple objects, select no change, and then simply adjust the margins.

I have script versions and applications created with Applescript studio, that have a much better interface. Scripts first
Code:
-- Annotate OmniGraffle objects by Dan Thomsen
-- customizable parameters
set label_font to "Arial Narrow"
set label_font_size to 12
set annotate_color to "Steel"
set annotate_thickness to 0.5

set layer_name to "Annotation Layer"
set annotate_label to "annotate here"

-- parameters that the user specifies
global horizontal_margin
global vertical_margin
global horizontal_position
global vertical_position
global annotation_position

set horizontal_margin to 20 -- default value
set vertical_margin to 20 -- default value

-- valid values are left, center right
set horizontal_position to "left" -- default value

-- valid values are top, middle, bottom
set vertical_position to "top" -- default value

-- constants
-- these are used to create magnets on the two ends and the middle of the edge
set left_edge to {{-0.5, -0.5}, {-0.5, 0}, {-0.5, 0.5}}
set right_edge to {{0.5, -0.5}, {0.5, 0}, {0.5, 0.5}}
set bottom_edge to {{-0.5, 0.5}, {0, 0.5}, {0.5, 0.5}}
set top_edge to {{-0.5, -0.5}, {0, -0.5}, {0.5, -0.5}}

-- variables



set annotation_size to {0, 0} --  used to store the size of the annotated text
set text_alignment to left -- default value
try
	tell front window of application "OmniGraffle Professional"
		activate
		
		-- all annotations are put on their own layer
		-- if the annotation layer does not exist create it
		if (name of layers) does not contain layer_name then
			make new layer at beginning of layers with properties {name:layer_name, visible:true, prints:true}
		end if
		
		-- get the annotation layer
		repeat with alayer in layers
			if name of alayer is equal to layer_name then
				set annotation_layer to alayer
				exit repeat
			end if
		end repeat
		
		set objects to selection
		if (length of objects < 1) then
			error "no objects selected"
		end if
		
		if not my prompt_user() then
			error "user abort"
		end if
		
		-- the position is saved in the annotation so that the margins can latter be adjusted by running the Reposition Annotation script
		set annotation_tag to {annotation:true, position:annotation_position}
		
		set object_count to 0
		
		-- we are going to draw an annotation at 0,0 just to get its actual size
		make new shape at beginning of graphics of annotation_layer with properties {origin:{0, 0}, draws stroke:no, fill:no fill, text:{size:label_font_size, color:annotate_color, font:label_font, alignment:text_alignment, text:(annotate_label)}, draws shadow:false, autosizing:full}
		set annotation_size to size of graphic 1
		
		-- now that we have the size we don't need the object any more
		delete graphic 1
		
		repeat with obj in objects
			set object_count to object_count + 1
			set obj_size to size of obj
			set obj_orig to origin of obj
			
			if horizontal_position is "left" then
				set x_pos to (item 1 of obj_orig) - horizontal_margin - (item 1 of annotation_size)
				set text_alignment to right
				set magnet_list to right_edge
				set x_header_start to x_pos + (item 1 of annotation_size)
			else if horizontal_position = "center" then
				set x_pos to (item 1 of obj_orig) + ((item 1 of obj_size) - (item 1 of annotation_size)) / 2
				set text_alignment to center
				if vertical_position = "top" then
					set magnet_list to bottom_edge
				else if vertical_position = "middle" then
					display alert "Invalid Placement." message "Cannot place an annotation in the center of the object." buttons {"OK"} default button 1
					exit repeat -- the script
				else -- vertical_position ="bottom"
					set magnet_list to top_edge
				end if
				
				set x_header_start to x_pos
			else
				set x_pos to (item 1 of obj_orig) + (item 1 of obj_size) + horizontal_margin
				set text_alignment to left
				set magnet_list to left_edge
				set x_header_start to x_pos
			end if
			
			if vertical_position = "top" then
				set y_pos to (item 2 of obj_orig) - vertical_margin - (item 2 of annotation_size)
				set y_header_start to y_pos
				set y_header_end to y_pos + (item 2 of annotation_size)
			else if vertical_position = "middle" then
				set y_pos to (item 2 of obj_orig) + ((item 2 of obj_size) - (item 2 of annotation_size)) / 2
				set y_header_start to y_pos
				set y_header_end to y_pos + (item 2 of annotation_size)
				if horizontal_position = "left" then
					set magnet_list to right_edge
				else if horizontal_position = "center" then
					display alert "Invalid Placement." message "Cannot place an annotation in the center of the object." buttons {"OK"} default button 1
					exit repeat -- the script
				else -- horizontal_position = right
					set magnet_list to left_edge
				end if
				
			else -- bottom
				set y_pos to (item 2 of obj_orig) + (item 2 of obj_size) + vertical_margin
				set y_header_start to y_pos
				set y_header_end to y_pos + (item 2 of annotation_size)
			end if
			
			make new shape at beginning of graphics of annotation_layer with properties {origin:{x_pos, y_pos}, size:annotation_size, draws stroke:no, fill:no fill, magnets:magnet_list, user data:annotation_tag, text:{size:label_font_size, color:annotate_color, font:label_font, alignment:text_alignment, text:(annotate_label)}, draws shadow:false, autosizing:full}
			
			set annotated_text to graphic 1
			set origin of annotated_text to {x_pos, y_pos}
			
			-- I have not been able to get connect the line directly between two objects
			-- I have to use the point list and then define source and destination after
			make new line at beginning of graphics of annotation_layer with properties {stroke color:annotate_color, thickness:annotate_thickness, point list:{x_pos, y_pos}}
			
			
			set connector_line to graphic 1
			set source of connector_line to obj
			set destination of connector_line to annotated_text
			set head magnet of connector_line to 2
			
			
			make new line at beginning of graphics of annotation_layer with properties {stroke color:annotate_color, thickness:annotate_thickness, point list:{{x_header_start, y_header_start}, {x_header_start, y_header_end}}}
			set header_line to graphic 1
			set source of header_line to annotated_text
			set tail magnet of header_line to 1
			set destination of header_line to annotated_text
			set head magnet of header_line to 3
			
		end repeat
		-- Need 'as list' if there's only one item. Pesky; took ages to figure out.
		-- object_count is multiplied by three because the text, header line and connector line are each object
		
		set selection to a reference to graphics 1 thru (object_count * 3) as list
		
		
	end tell
	
on error error_message
	tell front window of application "OmniGraffle Professional"
		activate
		--say error_message
		if not error_message is equal to "user abort" then
			display alert "No selection." message "This script adds an annotation to an object. Select some, then run it again." buttons {"OK"} default button 1
		end if
	end tell
end try


-- Ask the user to fill in the four global variables
on prompt_user()
	tell front window of application "OmniGraffle Professional"
		-- Prompt the user as to where to place annotation
		try
			set answer to choose from list {"NW", "N", "NE", "W", "E", "SW", "S", "SE"} with prompt "Placement:"
			
			if answer is false then return false
			
			set annotation_position to (item 1 of answer)
			set horizontal_position to my get_horizontal_position(annotation_position)
			set vertical_position to my get_vertical_position(annotation_position)
			
		on error error_message
			display alert error_message
			return false
		end try
		
		try
			set answer to display dialog "Enter horizontal margin" default answer "20"
			if answer is false then return false
			set horizontal_margin to text returned of answer as number
			
			set answer to display dialog "Enter vertical margin" default answer "20"
			if answer is false then return false
			set vertical_margin to text returned of answer as number
			
		on error error_message
			if error_message is "OmniGraffle Professional got an error: User canceled." then return false
			display alert error_message buttons {"OK"} default button 1
			return false
		end try
		return true
	end tell
end prompt_user



on get_horizontal_position(position)
	
	if {"NW", "W", "SW"} contains position then
		return ("left")
	else if {"N", "S"} contains position then
		return "center"
	else if {"NE", "E", "SE"} contains position then
		return "right"
	else
		return ("left")
	end if
end get_horizontal_position

on get_vertical_position(position)
	if {"NW", "N", "NE"} contains position then
		return ("top")
	else if {"W", "E"} contains position then
		return "middle"
	else if {"SW", "S", "SE"} contains position then
		return "bottom"
	else
		return ("top")
	end if
end get_vertical_position
 
 


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes


Similar Threads
Thread Thread Starter Forum Replies Last Post
AppleScript - How to Operate on Group of Selected Graphic Objects? trouble clef OmniGraffle General 1 2011-08-17 06:24 AM
Outlining objects Arild OmniGraffle General 0 2011-03-28 01:12 PM
Selecting Multiple Objects with Dragging, but Skip Underlying Objects ScottG OmniGraffle General 1 2011-01-07 07:02 AM
how do I annotate? clamshell OmniWeb General 2 2008-11-14 06:30 AM
Need Help - Feathering Objects priceless OmniGraffle General 1 2008-04-28 07:04 AM


All times are GMT -8. The time now is 03:16 AM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.