The Omni Group Forums

The Omni Group Forums (http://forums.omnigroup.com/index.php)
-   AppleScripting Omni Apps (http://forums.omnigroup.com/forumdisplay.php?f=46)
-   -   Beyond OmniGraffle styles (Plist inside script bundle) (http://forums.omnigroup.com/showthread.php?t=21187)

RobTrew 2011-05-22 10:26 AM

Beyond OmniGraffle styles (Plist inside script bundle)
 
OmniGraffle style are very useful, but for code-generated diagrams I need so save, edit and choose between named sets of settings (styles, in short) which go beyond the scope of the built-in styles.

Here, as a curiosity, and just in case others need to do anything similar, is a sketch of a way of maintaining such a set of styles in a plist file inside a script bundle. (There may well be simpler and more unix-like routes to the same thing - flat text files, for example :-)

(Note that the code needs to be saved as an .scptd bundle, rather than as a simple .scpt file).

[CODE]property pPlistPath : (POSIX path of (path to me)) & "Contents/Styles.plist"

property pLeft : 1
property pCentre : 2
property pRight : 3

property pTop : 4
property pBottom : 5


-- Arbitrary set of key-value pairs, which will become
-- the property names and property values of a custom style object
-- variants of which can be serialized as entries in a plist file
property plstDefaults : {
{"NumbersVisible", true},
{"AlignVert", pCentre},
{"AlignHoriz", pLeft},
{"XYOffset", {-0.15, -0.15}},
{"XYSize", {0.25, 0.25}},
{"NumFontName", "Gill Sans"},
{"NumFontColor", "Dark Gray"},
{"NumFontSize", 14},
{"LineColor", "Red"},
{"LineWeight", 2}
}

property pstrStyleEdit : "Edit current style"
property pstrStyleDelete : "Delete current style"
property plstStyleOps : {pstrStyleEdit, pstrStyleDelete}

property pstrBar : "_____________"
property pstrOther : "Continue"

on run
tell sPlistStyles
Initialize(plstDefaults, pPlistPath) -- Check that this script is in a bundle, and that we have a plist with at least a default style

set blnEsc to false
repeat while blnEsc = false
-- GET DEFINITION OF CURRENT STYLE AS AS STRING
set strSummary to GetSummary()

-- AND GET LIST OF AVAILABLE STYLES
set lstStyles to GetStyleNames()

-- AND INCLUDE STYLE OPERATIONS IN MENU
set lstMenu to lstStyles & {pstrBar} & plstStyleOps & {pstrBar} & {pstrOther}
tell application id "sevs"
activate
set varChoice to choose from list lstMenu with prompt strSummary with title "Diagram style"
end tell
if varChoice = false then return
set varChoice to first item of varChoice

-- EITHER EDIT/DELETE THE CURRENT STYLE
if varChoice is in plstStyleOps then
if varChoice = pstrStyleEdit then
EditStyle(strSummary) -- TO CREATE A NEW STYLE, EDIT THE NAME OF ANY EXISTING STYLE.
else if varChoice = pstrStyleDelete then
DeleteCurrentStyle()
end if
else
-- OR CHOOSE A DIFFERENT STYLE
if varChoice is in lstStyles then
ChooseStyle(varChoice)
else
-- OR MOVE ON TO OTHER MATTERS, USING THE CURRENT STYLE
if varChoice = pstrOther then set blnEsc to true
end if
end if
end repeat

set oStyle to GetStyle()
end tell


-- e.g.
LineColor of oStyle
end run

script sPlistStyles
property pSettingsPath : ""
property pDefaults : {}

on Initialize(lstKeyValueDefaults, strPlistPath)
if IsBundle() then
set my pSettingsPath to strPlistPath
set pDefaults to lstKeyValueDefaults
if FileExists(pSettingsPath) of sPlistStyles then
-- Try to get the default values from the plist
ChooseStyle("Default") of sPlistStyles
set blnFound to (count of (KeyValuePairs of my sCurrentStyle)) > 0
else
set blnFound to false
end if

if not blnFound then
tell my sCurrentStyle
set its KeyValuePairs to pDefaults
my StoreKeyValueSet(StyleName of it, its KeyValuePairs, pSettingsPath)
end tell
end if
else
error "Script not saved in .scptd bundle format."
end if
end Initialize

on GetSummary()
tell my sCurrentStyle
set strStyleName to StyleName of it
"CURRENT STYLE: \"" & strStyleName & "\"" & return & my List2Lines(KeyValuePairs of it, "")
end tell
end GetSummary

on GetStyle()
Settings() of my sCurrentStyle
end GetStyle

on ChooseStyle(strChoice)
set varPairs to ReadKeyValueSet(strChoice, pSettingsPath)
tell my sCurrentStyle
if varPairs is missing value then
set KeyValuePairs of it to pDefaults
else
set KeyValuePairs of it to varPairs
end if
set oStyleObject of it to missing value
set StyleName of it to strChoice
end tell
end ChooseStyle

on DeleteCurrentStyle()
set strStyleName to StyleName of my sCurrentStyle
if strStyleName ≠ "Default" then
DeleteKeyValueSet(strStyleName, pSettingsPath)
tell my sCurrentStyle
set KeyValuePairs of it to my pDefaults
set oStyleObject of it to missing value
set StyleName of it to "Default"
end tell
end if
end DeleteCurrentStyle

on IsBundle()
if IsFolder(POSIX path of (path to me)) then
return true
else
tell application id "sevs"
activate
display dialog "This script must be saved as a script bundle." & return & return &
"(.scptd rather than .scpt)" with title "Wrong script file format" buttons {"OK"} default button "OK"
end tell
return false
end if
end IsBundle

-- Note: the Finder's exists() function can not see inside the (script) bundle
on FileExists(strPath)
(do shell script ("test -e " & quoted form of strPath & "; echo $?")) = "0"
end FileExists

on IsFolder(strPath)
(do shell script ("test -d " & quoted form of strPath & "; echo $?")) = "0"
end IsFolder

script sCurrentStyle
property StyleName : "Default"
property KeyValuePairs : {}
property oStyleObject : missing value

on Settings()
if oStyleObject is missing value then set oStyleObject to MakeObject() of sPlistStyles
return oStyleObject
end Settings
end script

on MakeObject()
set strScript to "script" & return
repeat with oPair in KeyValuePairs of sCurrentStyle
set {strKey, varValue} to oPair
set cClass to class of varValue
if cClass is text then
set strValue to quote & varValue & quote
else if cClass is list then
if length of varValue > 0 then
set str to "{"
repeat with i from 1 to length of varValue
set str to str & item i of varValue & ", "
end repeat
set strValue to (text 1 thru -3 of str) & "}"
else
set strValue to "{}"
end if
else
set strValue to varValue
end if
set strScript to strScript & "property " & strKey & ": " & strValue & return
end repeat
set strScript to (strScript & "end script")
run script strScript
end MakeObject

on GetStyleNames()
set lstNames to ListKeyValueSets(pSettingsPath)
set my text item delimiters to linefeed
set lstNames to paragraphs of (do shell script "echo " & quoted form of (lstNames as text) & " | sort")
set my text item delimiters to space
lstNames
end GetStyleNames

-- Add a named list of key-value pairs to the PLIST file with the specified path (creating the PLIST file if needed)
on StoreKeyValueSet(strSetName, KeyValuePairs, strPlistPath)
set oPlist to GetPlistFile(strPlistPath)
tell application id "sevs"
tell contents of oPlist
tell property list items of contents of (make new property list item at end of property list items with properties {kind:record, name:strSetName})
repeat with i from 1 to length of KeyValuePairs
set {strKey, varValue} to item i of KeyValuePairs
make new property list item at end with properties {name:strKey, value:varValue}
end repeat
end tell
end tell
end tell
end StoreKeyValueSet

-- Delete (if it exists) the named list of key-value pairs from the PLIST file with the specified path
on DeleteKeyValueSet(strSetName, strPlistPath)
if FileExists(strPlistPath) then
set oPlist to GetPlistFile(strPlistPath)
tell application id "sevs"
tell contents of contents of oPlist
if (count of (property list items where name = strSetName)) > 0 then
set strDomain to text 1 thru -7 of strPlistPath -- remove .plist extension
do shell script "defaults delete " & quoted form of strDomain & space & quoted form of strSetName
end if
end tell
end tell
else
WarnNoPlist(strPlistPath)
end if
end DeleteKeyValueSet

-- Read if it exists the named list of key-value pairs from the PLIST file with the specified path
on ReadKeyValueSet(strSetName, strPlistPath)
if FileExists(strPlistPath) then
set oPlist to GetPlistFile(strPlistPath)
tell application id "sevs"
tell contents of contents of oPlist
set refMatches to a reference to (property list items where name = strSetName)
if (count of refMatches) > 0 then
set {lstName, lstValue} to {name, value} of (property list items of (first item of refMatches))
repeat with i from 1 to length of lstName
set item i of lstName to {item i of lstName, item i of lstValue}
end repeat
return lstName
else
return missing value
end if
end tell
end tell
else
WarnNoPlist(strPlistPath)
end if
end ReadKeyValueSet

-- Get a list of any named sets of key-value pairs in the PLIST file with the specified path
on ListKeyValueSets(strPlistPath)
if FileExists(strPlistPath) then
set oPlist to GetPlistFile(strPlistPath)
tell application id "sevs" to return name of (property list items of contents of contents of oPlist) -- returns a list
else
WarnNoPlist(strPlistPath)
end if
end ListKeyValueSets

on WarnNoPlist(strPlistPath)
tell application id "sevs"
activate
display alert "PLIST file not found: " & return & return & strPlistPath
end tell
return false
end WarnNoPlist

on GetPlistFile(strPathName)
tell application id "sevs"
if my FileExists(strPathName) then
return property list file strPathName
else
set oDict to make new property list item with properties {kind:record}
return (make new property list file with properties {contents:oDict, name:strPathName})
end if
end tell
end GetPlistFile

on EditStyle(strSummary)
tell application id "sevs"
activate
set varNew to display dialog "(To create a new style, edit the name of the current style)


Edit settings:" default answer strSummary with title pstrStyleEdit
set strEdited to text returned of varNew
end tell

-- Convert the edited lines back to a list of pairs
set lstSettings to Lines2List(strEdited)

-- assign the list of pairs back to the class and clear oStyleObject

if length of lstSettings > 0 then
set lstPairs to items 2 thru -1 of lstSettings
tell my sCurrentStyle
set KeyValuePairs of it to lstPairs
set oStyleObject of it to missing value
set strStyleName to item 2 of first item of lstSettings
set StyleName of it to strStyleName
end tell

StoreKeyValueSet(strStyleName, lstPairs, pSettingsPath)
end if
end EditStyle

on List2Lines(KeyValuePairs, strPrefix)
set str to ""
repeat with oPair in KeyValuePairs
set {strKey, varValue} to oPair
set cClass to class of varValue
if cClass is text then
set strValue to quote & varValue & quote
else if cClass is list then
set strValue to ListAsString(varValue)
else
set strValue to varValue
end if
set str to str & strPrefix & strKey & ": " & strValue & linefeed
end repeat
do shell script "echo " & quoted form of str & " | sort "
end List2Lines

on Lines2List(strLines)
set lstLines to paragraphs of strLines
if (count of lstLines) < 1 then return {}
repeat while last item of lstLines = ""
set lstLines to items 1 thru -2 of lstLines
end repeat
set my text item delimiters to ": "
set lst to {}
repeat with i from 1 to length of lstLines
set lstPair to text items of item i of lstLines
if length of lstPair = 2 then
set item 2 of lstPair to run script item 2 of lstPair
set end of lst to lstPair
end if
end repeat
lst
end Lines2List

on ListAsString(varValue)
if length of varValue > 0 then
set str to "{"
repeat with i from 1 to length of varValue
set str to str & item i of varValue & ", "
end repeat
(text 1 thru -3 of str) & "}"
else
"{}"
end if
end ListAsString

end script

[/CODE]

RobTrew 2011-05-23 08:22 AM

FWIW I have generalized the above with a function which serializes a specified sub-set of the properties of an object into a list of {[I]property name[/I], [I]property value[/I]} pairs, which can be written to a plist file.

Inelegant, but serviceable enough, I think:

[CODE]-- SERIALIZE THE RELEVANT PROPERTIES OF AN OBJECT AS A LIST OF KEY-VALUE PAIRS,
-- TO BE WRITTEN TO A PLIST FILE
on Serialize(oObject, lstProps)
set lst to {}
repeat with oKey in lstProps
set end of lst to {oKey, my GetProp(oKey, oObject)}
end repeat
return lst
end Serialize

on GetProp(strPropName, oObject)
run script "
on run {refObject}
get " & strPropName & " of refObject
end run
" with parameters {oObject}
end GetProp[/CODE]


All times are GMT -8. The time now is 10:36 PM.

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