Skip to content

Commit b6eff91

Browse files
committed
build mac FORCE app with applescript launcher
1 parent a91046f commit b6eff91

File tree

6 files changed

+120
-37
lines changed

6 files changed

+120
-37
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ romMeta.xml
1414

1515
# Ignore built executables
1616
build
17+
force_install
18+
*.app
1719

1820
# Ignore certain GUI files
1921
.forceuirc

package/build_force_mac.sh

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,32 @@
1+
# Freeze the FORCE app using cx_Freeze. We require a suitable python environment to be active.
2+
# set -e
3+
# python setup.py install_exe --install-dir force_install
4+
5+
# Set up the FORCE application bundle
6+
# We'll set up the app so that some FORCE launcher script is the main executable, and the RAVEN,
7+
# HERON, and TEAL executables are in the Resources directory.
8+
# Build the initial app from the force_launcher.scpt AppleScript
9+
osacompile -o FORCE.app force_launcher.scpt
10+
# Now copy over the force_install directory contents to the application's Resources directory
11+
cp -R force_install/* FORCE.app/Contents/Resources/
12+
# Overwrite the app's icon with the FORCE icon
13+
cp FORCE.icns FORCE.app/Contents/Resources/applet.icns
14+
115
# Create a new disk image
216
hdiutil create -size 3g -fs HFS+ -volname "FORCE" -o force_build.dmg
317

418
# Mount the new disk image
519
hdiutil attach force_build.dmg -mountpoint /Volumes/FORCE
620

7-
# Mount the existing .dmg files
8-
hdiutil attach Workbench-5.4.1.dmg -mountpoint /Volumes/Workbench
9-
10-
# Copy the contents of the force_install directory and the Workbench .dmg file to the new disk image.
11-
mkdir -p FORCE.app/Contents/MacOS
12-
mkdir -p FORCE.app/Contents/Resources
13-
# TODO: move icons to Resources?
14-
cp -R force_install/* FORCE.app/Contents/MacOS/
15-
cp -R force_install/* /Volumes/FORCE/
16-
cp -R /Volumes/Workbench/* /Volumes/FORCE/
17-
18-
# Create the info.plist file with app metadata
19-
# TODO: Which app do we point to?
20-
cat <<EOF > FORCE.app/Contents/Info.plist
21-
<?xml version="1.0" encoding="UTF-8"?>
22-
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
23-
<plist version="1.0">
24-
<dict>
25-
<key>CFBundleName</key>
26-
<string>FORCE</string>
27-
<key>CFBundleDisplayName</key>
28-
<string>FORCE</string>
29-
<key>CFBundleIdentifier</key>
30-
<string></string>
31-
<key>CFBundleVersion</key>
32-
<string>0.1</string>
33-
<key>CFBundleExecutable</key>
34-
<string>my_script.sh</string>
35-
<key>CFBundlePackageType</key>
36-
<string>APPL</string>
37-
</dict>
38-
</plist>
39-
EOF
21+
# Mount the existing .dmg file file Workbench
22+
# hdiutil attach Workbench-5.4.1.dmg -mountpoint /Volumes/Workbench
23+
24+
# Move the FORCE app to the disk image
25+
cp -R FORCE.app /Volumes/FORCE/
26+
# cp -R /Volumes/Workbench/* /Volumes/FORCE/
4027

4128
# Unmount all the disk images
42-
hdiutil detach /Volumes/Workbench
29+
# hdiutil detach /Volumes/Workbench
4330
hdiutil detach /Volumes/FORCE
4431

4532
# Convert to read-only compressed image

package/force_launcher.scpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
set options to {"HERON", "RAVEN", "TEAL", "Quit"}
2+
3+
set resourceName to "heron"
4+
set filePathName to quoted form of POSIX path of (path to resource resourceName) as text
5+
6+
set selectedOption to choose from list options with title "FORCE Launcher" with prompt "Which FORCE application woudl you like to use?" default items {"HERON"}
7+
8+
if selectedOption is false then
9+
display dialog "No option selected. Exiting..." buttons {"OK"} default button "OK"
10+
else
11+
set selectedOption to item 1 of selectedOption
12+
if selectedOption is "HERON" then
13+
set resourceName to "heron"
14+
else if selectedOption is "RAVEN" then
15+
set resourceName to "raven_framework"
16+
else if selectedOption is "TEAL" then
17+
set resourceName to "teal"
18+
else if selectedOption is "Quit" then
19+
display dialog "Exiting..." buttons {"OK"} default button "OK"
20+
end if
21+
set filePathName to quoted form of POSIX path of (path to resource resourceName) as text
22+
do shell script filePathName
23+
end if

package/force_logo.icns

830 KB
Binary file not shown.

package/ui/main.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
from ui.controllers import Controller
44
from ui.views import View
55

6-
from typing import Optional
7-
import argparse
8-
96

107
def run_from_gui(func: Callable, **kwargs):
118
"""

package/ui/utils.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import xml.etree.ElementTree as ET
2+
import os
3+
import subprocess
4+
import platform
5+
import shutil
6+
7+
8+
def check_parallel(path) -> bool:
9+
"""
10+
Checks if a ravenframework input file uses parallel processing. This poses a problem for the executable
11+
on MacOS and possibly Linux.
12+
13+
@In, path, str, path to the input file
14+
@Out, is_parallel, bool, True if parallel processing is used, False otherwise
15+
"""
16+
is_parallel = False
17+
18+
tree = ET.parse(path)
19+
tree.find()
20+
21+
return is_parallel
22+
23+
24+
def find_workbench():
25+
"""
26+
Finds the NEAMS Workbench executable
27+
"""
28+
workbench_path = None
29+
if platform.system() == "Windows":
30+
if os.environ.get('WORKBENCH_PATH'):
31+
workbench_path = os.environ['WORKBENCH_PATH']
32+
else:
33+
workbench_path = shutil.which('workbench')
34+
elif platform.system() == "Darwin":
35+
# Look in the /Applications directory for a directory starting with "Workbench"
36+
for app in os.listdir("/Applications"):
37+
if app.startswith("Workbench") and os.path:
38+
workbench_path = os.path.join("/Applications", app, "Contents/MacOS/Workbench")
39+
break
40+
else:
41+
print("ERROR: Could not find the NEAMS Workbench application in the /Applications directory. "
42+
"Has Workbench been installed?")
43+
else: # Linux, not yet supported
44+
print("Automatic connection of FORCE tools to the NEAMS Workbench is not yet supported on Linux.")
45+
return workbench_path
46+
47+
48+
def run_in_workbench(file: str | None = None):
49+
"""
50+
Opens the given file in the NEAMS Workbench
51+
@ In, file, str, optional, the file to open in NEAMS Workbench
52+
"""
53+
# Find the workbench executable
54+
workbench_path = find_workbench()
55+
if workbench_path is None:
56+
print("ERROR: Could not find the NEAMS Workbench executable. Please set the "
57+
"WORKBENCH_PATH environment variable or add it to the system path.")
58+
raise RuntimeError
59+
60+
# Open the file in the workbench
61+
command = workbench_path
62+
# Currently, we're only able to open the MacOS version of Workbench by opening the app itself.
63+
# This does not accept a file as an argument, so users will need to open Workbench, then open
64+
# the desired file manually from within the app.
65+
if file is not None and platform.system() == "Windows":
66+
command += ' ' + file
67+
68+
if platform.system() == "Windows":
69+
os.system(command)
70+
elif platform.system() == "Darwin":
71+
subprocess.call(["/usr/bin/open", "-n", "-a", workbench_path])
72+
else:
73+
print("ERROR: Automatic connection of FORCE tools to the NEAMS Workbench is only supported "
74+
"on Windows and MacOS. Please open Workbench manually and open the desired file.")

0 commit comments

Comments
 (0)