Skip to content

Commit 13d8b8f

Browse files
Andrew MurrayAndrew Murray
authored andcommitted
Initial commit
0 parents  commit 13d8b8f

File tree

6 files changed

+240
-0
lines changed

6 files changed

+240
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
nest
2+
=========
3+
4+
Simple webpage presentation application
5+
6+
##What is it?
7+
8+
In Mac OS X 10.9, I discovered that if spaces are linked, you are unable to present a webpage fullscreen on a secondary display without losing control of your primary display. This was problematic, and so I put together a simple Python application to fix the problem.
9+
10+
Since projectors are sometimes put into widescreen mode, this also solves the problem of how to rescale a webpage so that it can be viewed correctly. A widescreen mode simply adds a CSS transform to the body of the page.
11+
12+
##Why is it called Nest?
13+
14+
The original situation I used it in was to present a webpage for my mobile app, CarrierPigeon. So I continued with the bird theme and called it Nest.

nest.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import wx
2+
import wx.html2
3+
4+
class BrowserWindow(wx.Frame):
5+
def __init__(self, *args, **kwds):
6+
wx.Frame.__init__(self, *args, **kwds)
7+
8+
sizer = wx.BoxSizer(wx.VERTICAL)
9+
self.browser = wx.html2.WebView.New(self)
10+
sizer.Add(self.browser, 1, wx.EXPAND, 10)
11+
self.SetSizer(sizer)
12+
13+
menuBar = wx.MenuBar()
14+
15+
menu = wx.Menu()
16+
menuItem = menu.Append(wx.ID_ANY, 'Open URL...\tCtrl+O')
17+
self.SetAcceleratorTable(wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('O'), menuItem.GetId())]))
18+
self.Bind(wx.EVT_MENU, self.openURL, menuItem)
19+
20+
self.widescreenMenuItem = menuItem = menu.Append(wx.ID_ANY, 'Switch to widescreen mode\tCtrl+T')
21+
self.SetAcceleratorTable(wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('T'), menuItem.GetId())]))
22+
self.Bind(wx.EVT_MENU, self.switchWidescreen, menuItem)
23+
menuBar.Append(menu, '&File')
24+
25+
self.SetMenuBar(menuBar)
26+
27+
self.widescreen = False
28+
29+
#Initially, wx.Frames are not visible
30+
self.hidden = True
31+
32+
self.openURL()
33+
34+
def openURL(self, event = None):
35+
dialog = wx.TextEntryDialog(self, "Load Page", "Please enter page url")
36+
if dialog.ShowModal() != wx.ID_OK:
37+
return
38+
39+
url = dialog.GetValue()
40+
if not url:
41+
return
42+
43+
dialog.Destroy()
44+
45+
if not url.startswith('http://') or url.startswith('https://'):
46+
url = 'http://'+url
47+
48+
self.LoadPage(url)
49+
50+
def LoadPage(self, url):
51+
self.browser.LoadURL(url)
52+
53+
if self.hidden:
54+
self.Show()
55+
#Alternatively, the window could be shown only on load
56+
#self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.Show, self.browser)
57+
58+
self.hidden = False
59+
60+
def switchWidescreen(self, event):
61+
self.widescreen = not self.widescreen
62+
63+
if self.widescreen:
64+
stretchRatio = "0.7"
65+
# When changing from 4:3 to 16:9, the logical value for this argument would be 0.5625
66+
# However, experimentally, I have found that 0.7 works. I am unsure about why this discrepancy exists
67+
68+
script = """
69+
var width = document.getElementsByTagName("body")[0].offsetWidth / """+stretchRatio+""";
70+
document.getElementsByTagName("body")[0].setAttribute('style','-webkit-transform: scaleX("""+stretchRatio+"""); width: '+width+'px; position: absolute; left: -'+(width * (1 - """+stretchRatio+""") / 2)+'px;');
71+
"""
72+
else:
73+
#If it is changing from widescreen to normal, remove the style argument
74+
script = """
75+
document.getElementsByTagName("body")[0].removeAttribute('style');
76+
"""
77+
self.browser.RunScript(script)
78+
79+
self.widescreenMenuItem.SetItemLabel('Switch '+('from' if self.widescreen else 'to')+' widescreen mode\tCtrl+T')
80+
81+
82+
def getScreenSize():
83+
displayNumber = 1 if wx.Display.GetCount() == 2 else 0
84+
85+
display = wx.Display(displayNumber)
86+
screensize = display.GetGeometry()
87+
88+
if displayNumber == 0:
89+
#Let's not cover up the main screen completely
90+
scale = 0.75
91+
92+
screensize.SetWidth(screensize.GetWidth() * scale)
93+
screensize.SetHeight(screensize.GetHeight() * scale)
94+
screensize.SetX(screensize.GetX() + screensize.GetWidth() * (1 - scale) / 2)
95+
screensize.SetY(screensize.GetY() + screensize.GetHeight() * (1 - scale) / 2)
96+
return screensize
97+
98+
app = wx.App()
99+
100+
dialog = BrowserWindow(None, -1, style=wx.NO_BORDER)
101+
dialog.SetRect(getScreenSize())
102+
103+
app.MainLoop()

resources/Info.plist

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>English</string>
7+
<key>CFBundleDisplayName</key>
8+
<string>Nest</string>
9+
<key>CFBundleDocumentTypes</key>
10+
<array>
11+
<dict>
12+
<key>CFBundleTypeOSTypes</key>
13+
<array>
14+
<string>****</string>
15+
<string>fold</string>
16+
<string>disk</string>
17+
</array>
18+
<key>CFBundleTypeRole</key>
19+
<string>Viewer</string>
20+
</dict>
21+
</array>
22+
<key>CFBundleExecutable</key>
23+
<string>Nest</string>
24+
<key>CFBundleIconFile</key>
25+
<string>NestLogo.icns</string>
26+
<key>CFBundleIdentifier</key>
27+
<string>com.radartech.presentation.Nest</string>
28+
<key>CFBundleInfoDictionaryVersion</key>
29+
<string>6.0</string>
30+
<key>CFBundleName</key>
31+
<string>Nest</string>
32+
<key>CFBundlePackageType</key>
33+
<string>APPL</string>
34+
<key>CFBundleShortVersionString</key>
35+
<string>0.0.1</string>
36+
<key>CFBundleSignature</key>
37+
<string>????</string>
38+
<key>CFBundleVersion</key>
39+
<string>0.0.1</string>
40+
<key>LSHasLocalizedDisplayName</key>
41+
<false/>
42+
<key>NSAppleScriptEnabled</key>
43+
<false/>
44+
<key>NSHumanReadableCopyright</key>
45+
<string>© Radartech</string>
46+
<key>NSMainNibFile</key>
47+
<string>MainMenu</string>
48+
<key>NSPrincipalClass</key>
49+
<string>NSApplication</string>
50+
<key>PyMainFileNames</key>
51+
<array>
52+
<string>__boot__</string>
53+
</array>
54+
<key>PyOptions</key>
55+
<dict>
56+
<key>alias</key>
57+
<false/>
58+
<key>argv_emulation</key>
59+
<true/>
60+
<key>no_chdir</key>
61+
<false/>
62+
<key>optimize</key>
63+
<integer>0</integer>
64+
<key>prefer_ppc</key>
65+
<false/>
66+
<key>site_packages</key>
67+
<false/>
68+
<key>use_pythonpath</key>
69+
<false/>
70+
</dict>
71+
<key>PyResourcePackages</key>
72+
<array>
73+
</array>
74+
<key>PyRuntimeLocations</key>
75+
<array>
76+
<string>@executable_path/../Frameworks/Python.framework/Versions/2.7/Python</string>
77+
</array>
78+
<key>PythonInfoDict</key>
79+
<dict>
80+
<key>PythonExecutable</key>
81+
<string>/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python</string>
82+
<key>PythonLongVersion</key>
83+
<string>2.7.5 (default, Aug 17 2011, 13:04:27)
84+
[GCC 4.0.1 (Apple Inc. build 5465)]</string>
85+
<key>PythonShortVersion</key>
86+
<string>2.7</string>
87+
<key>py2app</key>
88+
<dict>
89+
<key>alias</key>
90+
<false/>
91+
<key>template</key>
92+
<string>app</string>
93+
<key>version</key>
94+
<string>0.7.3</string>
95+
</dict>
96+
</dict>
97+
</dict>
98+
</plist>

resources/Nest.icns

350 KB
Binary file not shown.

resources/Nest.png

197 KB
Loading

setup.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
This is a setup.py script generated by py2applet
3+
4+
Usage:
5+
python setup.py py2app
6+
"""
7+
8+
from setuptools import setup
9+
10+
APP = ['nest.py']
11+
DATA_FILES = []
12+
13+
OPTIONS = {
14+
'iconfile':'resources/Nest.icns',
15+
'plist':'resources/Info.plist'
16+
}
17+
18+
setup(
19+
app=APP,
20+
data_files=DATA_FILES,
21+
options={'py2app': OPTIONS},
22+
version='0.0.1',
23+
author='Andrew Murray',
24+
setup_requires=['py2app'],
25+
)

0 commit comments

Comments
 (0)