Automatically resizing and positioning an OmniOutliner window
When I'm working with a single monitor I often have OO3 as a full-height window in the right-hand third of the screen, and some other application in the left-hand two thirds. (Taking notes, or working through some kind of list in OO3).
Here is a script which will resize and reposition the selected window (of any application, as it happens) to the rightmost third of the screen. Edit the 1st four property values to get the window size and position that you want. (I personally use 3 or 4 of these scripts, with keystrokes assigned to each). [CODE]-- SET SIZE AND POSITION OF SELECTED WINDOW (ANY APPLICATION) -- NB: -- 1. only for single monitor setups -- 2. Not all windows can be arbitrarily resized ) -- EXAMPLE: A full-height window, rightmost third of the screen: -- POSITION (origin: top left) property pPosnAcross : 2 / 3 property pPosnDown : 0 -- SIZE (units: proportion of the desktop) property pSizeAcross : 1 / 3 property pSizeDown : 1 property pMenuHeight : 22 tell application id "com.apple.finder" tell window of desktop set {_, _, lngwidth, lngHeight} to bounds set lngHeight to lngHeight - pMenuHeight end tell end tell tell application id "com.apple.systemevents" tell front window of (first application process where frontmost = true) set position to {pPosnAcross * lngwidth, (pPosnDown * lngHeight) + pMenuHeight} set size to {pSizeAcross * lngwidth, pSizeDown * lngHeight} end tell end tell [/CODE] |
FWIW a version which should work with single or multiple display systems, and can be run from the command line with four arguments: [I]OriginX, OriginY, Width, Depth[/I] [and, optionally [I]Index[/I] - see next post].
(Useful for assigning keystrokes to a variety of screen positions with something like Keyboard Maestro). [CODE]property pVer : "1.2" property pTitle : "Resize and reposition window by % of screen" & tab & pVer -- SET SIZE AND POSITION OF SELECTED WINDOW (ANY APPLICATION) -- (WORKS WITH SINGLE OR DUAL DISPLAY SYSTEMS) -- Can be also used with arguments from the command line. -- e.g. if saved as ~/Library/Scripts/PlaceWin.scpt then, -- to resize the selected window to the left third of the screen: -- osascript ~/Library/Scripts/PlaceWin.scpt 0 0 0.333 1 -- where the parameters are OriginX OriginY Width Depth -- THUS, TO RESTORE A WORKSPACE, A COMMAND LINE BATCH SCRIPT LIKE -- open -a 'omnioutliner professional' -- osascript ~/Library/Scripts/PlaceWin.scpt 0 0 0.667 1 2 -- open -a 'DEVONthink Pro' -- osascript ~/Library/Scripts/PlaceWin.scpt 0 0 0.667 1 1 -- (Which can be assigned to a keystroke with something like KeyBoard Maestro) -- Version history -- Ver 0.4 Waits, up to pTimeOut seconds, for the frontmost process to present a window (useful if an app is loading) -- Ver 0.5 Should support more than two monitors. Code has been slightly simplified. -- Ver 0.7 Cycles between one-corner rectangles, and their left-right and top-down complements -- Ver 0.8 Accepts a fifth argument: an index which suppresses toggling and selects a particular transform of the basic coordinates (usually 1) -- (Useful when calling the script after an open -b or open -a to launch an application) -- Ver 0.9 if the height or width is 0.5 toggles between vertical and horizontal splits -- (Economises on the allocation of keyboard shortcuts through something like Keyboard Maestro) -- Ver 1.0 if the height or width is < 0.5 and expressible as 1/N where N is a small integer (≤ 6), then cycles between the N fitting rectangles -- Ver 1.1 Restores compensation for menu bar space (though Microsoft Word still recalcitrant with landscape splits) -- Ver 1.2 Defaults to the primary rectangle on the first call with a particular set of parameters -- (Begins to cycle through any screen-tiling transforms on the first repeated call). -- DEFAULT: A full-height window, rightmost third of the screen: -- NB (Not all windows can be arbitrarily resized) -- UNITS - proportion of whichever screen is displaying the selected window -- POSITION - (origin: top left) property pPosnAcross : 0 property pPosnDown : 0 -- SIZE property pSizeAcross : 1 / 3 property pSizeDown : 1 property pblnMenuWindow : false property pMenuHeight : 22 property pstrWinPrefsPath : "/Library/Preferences/com.apple.windowserver.plist" property pTimeout : 10 -- Maximum number of seconds to wait for a loading app to present a window property plstDisplays : {} property piBox : 0 property piSpecific : missing value property pblnRepeat : false on run argv -- PROCESS ANY ARGUMENTS PASSED BY AN OSASCRIPT SHELL COMMAND try if class of argv is list then -- FIRST FOUR ARGUMENTS REQUIRED: OriginX, OriginY, Width, Height set refPosnSize to a reference to items 1 thru 4 of argv repeat with i from 1 to 4 set item i of refPosnSize to (item i of refPosnSize) as real end repeat -- RECORD WHETHER THESE ARGUMENTS MATCH THOSE OF THE PREVIOUS CALL -- (WE MAY NEED TO CYCLE TO THE NEXT COMPLEMENTARY TRANSFORM) set pblnRepeat to (contents of refPosnSize) = {pPosnAcross, pPosnDown, pSizeAcross, pSizeDown} -- AND UPDATE THE PERSISTENT PARAMETERS IF THEY HAVE CHANGED if not pblnRepeat then set {pPosnAcross, pPosnDown, pSizeAcross, pSizeDown} to refPosnSize -- HANDLE THE OPTIONAL FIFTH ARGUMENT -- (AN INDEX TO A SPECIFIC COMPLEMENTARY TRANSFORM (LEFT/RIGHT OR TOP/DOWN) OF THE BASE RECTANGLE) -- USEFUL IF THE OSASCRIPT CALL FOLLOWS AN OPEN -A CALL -- WHICH AIMS TO OPEN A NAMED APP TO A SPECIFIC WINDOW SIZE/POSN if length of argv > 4 then set piSpecific to (item 5 of argv) else set piSpecific to missing value end if -- IF THIS IS NOT A REPEATED CALL WITH THE SAME ARGUMENTS, -- (AND NO TRANSFORM HAS BEEN SPECIFIED), -- THEN DEFAULT TO THE BASE RECTANGLE (TRANSFORM 1) if (not pblnRepeat) and (piSpecific is missing value) then set piSpecific to 1 end if on error strError return strError end try -- NOW REPOSITION AND RESIZE THE FRONT WINDOW, -- USING THE GIVEN PROPORTIONS OF THE CURRENT SCREEN SIZE ReSizePosn() end run -- GET THE CURRENT SCREEN SIZE, -- AND MOVE AND RESIZE THE FRONT WINDOW USING PROPORTIONAL DIMENSIONS on ReSizePosn() -- GET THE PROPERTIES OF THE REMEMBERED DISPLAYS tell application id "com.apple.systemevents" tell contents of property list file pstrWinPrefsPath set plstDisplays to (first item of ((value of (property list item "DisplaySets")) as list)) end tell -- GET THE FRONT WINDOW AND ITS POSITION set refProc to a reference to (first application process where frontmost = true) set procFront to (first application process where frontmost = true) set oWin to missing value repeat with i from 1 to pTimeout * 2 if (count of windows of procFront) > 0 then exit repeat do shell script "sleep 0.5" end repeat set blnMSWord to (name of procFront) contains "Microsoft Word" set oWin to front window of procFront if oWin is missing value then return set {lngWinX, lngWinY} to position of oWin -- FIND THE DISPLAY CONTAINING THE TOP LEFT CORNER OF THIS WINDOW set blnFound to false repeat with recDisplay in plstDisplays set {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown} to {OriginX, OriginY, Width, Height} of recDisplay if ((lngWinX ≥ lngScreenX) and (lngWinX < (lngScreenX + lngScreenAcross)) and ¬ ((lngWinY ≥ lngScreenY) and (lngWinY < (lngScreenY + lngScreenDown)))) then set pblnMenuWindow to {lngScreenX, lngScreenY} = {0, 0} set blnFound to true exit repeat end if end repeat if not blnFound then return set lstBoxes to my GetTransforms({pPosnAcross, pPosnDown, pSizeAcross, pSizeDown}, {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown}) if piSpecific is missing value then set piBox to piBox + 1 if piBox > length of lstBoxes then set piBox to 1 else try set piBox to (piSpecific as integer) -- specified as fifth argument of the command line on error set piBox to 1 end try end if set {lngWinX, lngWinY, lngWinWidth, lngWinHeight} to item piBox of lstBoxes if pblnMenuWindow then set lngWinY to lngWinY + pMenuHeight tell oWin if blnMSWord then tell application id "com.Microsoft.Word" tell front window of active document set position to {lngWinX, lngWinY + (pMenuHeight)} set width to lngWinWidth set height to lngWinHeight end tell end tell else set {position, size} to {{lngWinX, lngWinY}, {lngWinWidth, lngWinHeight}} end if end tell end tell return end ReSizePosn -- FOR RECTANGLES WHICH INCLUDE ONE OR TWO CORNERS OF THE SCREEN, -- OR TOUCH OPPOSITE EDGES OF THE SCREEN, AND HAVE A HEIGHT OR WIDTH -- WHICH IS A SIMPLE FRACTION OF THE CORRESPONDING SCREEN DIMENSION -- GENERATE THE SCREEN-TILING SET OF COMPLEMENTARY RECTANGLES. -- (REPEATED CALLS OF THE SCRIPT WITH THE SAME PARAMETERS CYCLE THROUGH THESE COMPLEMENTARY TRANSFORMS, -- ALLOWING SIMPLE TILING OF THE SCREEN WITH A SMALL NUMBER OF ASSIGNED KEYSTROKES) on GetTransforms({pPosnAcross, pPosnDown, pSizeAcross, pSizeDown}, {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown}) if pblnMenuWindow then set lngScreenDown to lngScreenDown - pMenuHeight --set lngScreenY to lngScreenY + pMenuHeight end if set {lngX, lngY, lngwidth, lngHeight} to {(pPosnAcross * lngScreenAcross) + lngScreenX, (pPosnDown * lngScreenDown) + lngScreenY, pSizeAcross * lngScreenAcross, pSizeDown * lngScreenDown} set {pSizeAcross, pSizeDown} to {pSizeAcross as real, pSizeDown as real} set {lngDeltaX, lngDeltaY} to {0, 0} if lngX = 0 then set lngDeltaX to lngwidth if lngY = 0 then set lngDeltaY to lngHeight if (pSizeAcross = 1.0) or (pSizeDown = 1.0) then -- Single split left/right or up/down if pSizeAcross = 1.0 then -- UP DOWN if pSizeDown = 0.5 then -- (vertical and horizontal splits) set {lngAltwidth, lngAltHeight} to {pSizeDown * lngScreenAcross, pSizeAcross * lngScreenDown} {{lngX, lngY, lngwidth, lngHeight}, {lngX, lngDeltaY, lngwidth, lngScreenDown - lngHeight}, ¬ {0, 0, lngAltwidth, lngAltHeight}, {lngAltwidth, 0, lngScreenAcross - lngAltwidth, lngAltHeight}} else if pSizeDown ≥ (1 / 6) and IsSimpleFraction(pSizeDown) then set lst to {} set lngDeltaY to 0 repeat with i from 1 to (1 / pSizeDown) as integer set end of lst to {lngX, lngDeltaY, lngwidth, lngHeight} set lngDeltaY to lngDeltaY + lngHeight end repeat lst else {{lngX, lngY, lngwidth, lngHeight}, {lngX, lngDeltaY, lngwidth, lngScreenDown - lngHeight}} end if else -- LEFT RIGHT if pSizeAcross = 0.5 then set {lngAltwidth, lngAltHeight} to {pSizeDown * lngScreenAcross, pSizeAcross * lngScreenDown} {{lngX, lngY, lngwidth, lngHeight}, {lngDeltaX, lngY, lngScreenAcross - lngwidth, lngHeight}, ¬ {0, 0, lngAltwidth, lngAltHeight}, {0, lngAltHeight, lngAltwidth, lngScreenDown - lngAltHeight}} else if pSizeAcross ≥ (1 / 6) and IsSimpleFraction(pSizeAcross) then set lst to {} set lngDeltaX to 0 repeat with i from 1 to (1 / pSizeAcross) as integer set end of lst to {lngDeltaX, lngY, lngwidth, lngHeight} set lngDeltaX to lngDeltaX + lngwidth end repeat lst else {{lngX, lngY, lngwidth, lngHeight}, {lngDeltaX, lngY, lngScreenAcross - lngwidth, lngHeight}} end if end if else -- does this have at least one corner ? (at {0,0} or (height+y)=1) or ((width+x)=1) if ({lngX, lngY} = {0, 0}) or AlmostOne(pSizeDown + pPosnDown) or AlmostOne(pSizeAcross + pPosnAcross) then {{lngX, lngY, lngwidth, lngHeight}, ¬ {lngX, lngDeltaY, lngwidth, lngScreenDown - lngHeight}, ¬ {lngDeltaX, lngDeltaY, lngScreenAcross - lngwidth, lngScreenDown - lngHeight}, ¬ {lngDeltaX, lngY, lngScreenAcross - lngwidth, lngHeight}} else {{lngX, lngY, lngwidth, lngHeight}} end if end if end GetTransforms on AlmostOne(rNumber) (1 - rNumber) < 0.01 end AlmostOne on IsSimpleFraction(nNumber) if nNumber > 0.5 then return false else set n to 1 / nNumber Abs((n as real) - (n as integer)) < 0.01 end if end IsSimpleFraction on Abs(n) if n < 0 then -n else n end if end Abs [/CODE] [COLOR="White"]--[/COLOR] |
Thus to restore a workspace with, for example, OO3 in the right-hand third of the screen, and DevonThink in the left-hand two thirds, you could use a batch of shell commands like this:
[CODE] #!/bin/sh open -a 'DEVONthink Pro' osascript ~/Library/Scripts/PlaceWin.scpt 0 0 0.667 1 1 open -a 'omnioutliner professional' osascript ~/Library/Scripts/PlaceWin.scpt 0 0 0.667 1 2 [/CODE] (The fifth argument is an index. Repeated calls with the same parameters make the script cycle through complementary screen-tiling rectangles. Index 1 gives the primary rectangle, Index 2 gives the first complementary tile. In this case the right-hand third of the screen, to fill the screen by complementing the left-hand two thirds. Automatic cycling through complementary tiles makes it possible to fill the screen quickly using a small number of assigned keystrokes). ( Note that for this to work well you probably need to set your oo3 preference to [I]OmniOutliner > Preferences > General > When OmniOutliner Starts Up > Create a new document[/I] ) A shell script like this can, of course, be assigned to a key-stroke using, for example, FastScripts or Keyboard Maestro. [COLOR="White"]--[/COLOR] |
All times are GMT -8. The time now is 02:26 PM. |
Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.