Skip to content

Commit

Permalink
Merge pull request #399 from obulat/icons
Browse files Browse the repository at this point in the history
Added Icons, menus and toolbars to Winforms backend.
  • Loading branch information
freakboy3742 committed Apr 15, 2018
2 parents db26e29 + b30fd8e commit e8ed74c
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 33 deletions.
26 changes: 24 additions & 2 deletions src/cocoa/toga_cocoa/widgets/icon.py
@@ -1,8 +1,30 @@
import os

from toga import Icon as toga_Icon
from toga_cocoa.libs import NSImage


class Icon:
def __init__(self, interface):
self.interface = interface
interface.__impl = self
self.native = NSImage.alloc().initWithContentsOfFile(interface.filename)
self.interface._impl = self
file_path, file_extension = os.path.splitext(self.interface.filename)
valid_icon_extensions = ('.png', '.bmp', '.ico')

if file_extension == '.icns':
self.native = NSImage.alloc().initWithContentsOfFile(self.interface.filename)
elif os.path.isfile(file_path + '.icns'):
self.native = NSImage.alloc().initWithContentsOfFile(file_path + '.icns')
elif file_extension in valid_icon_extensions:
self.native = NSImage.alloc().initWithContentsOfFile(self.interface.filename)
elif os.path.isfile(file_path + '.png'):
self.native = NSImage.alloc().initWithContentsOfFile(file_path + '.png')
elif os.path.isfile(file_path + '.bmp'):
self.native = NSImage.alloc().initWithContentsOfFile(file_path + '.bmp')
else:
print("[Cocoa] No valid icon format available for {}; "
"fall back on Tiberius instead".format(
self.interface.filename))
tiberius_file = toga_Icon.TIBERIUS_ICON.filename + '.icns'
self.interface.icon = toga_Icon.TIBERIUS_ICON
self.native = NSImage.alloc().initWithContentsOfFile(tiberius_file)
2 changes: 1 addition & 1 deletion src/core/tests/test_app.py
Expand Up @@ -34,7 +34,7 @@ def test_app_icon(self):
self.assertEqual(self.app.icon, self.app.default_icon)

# Set the icon to a different resource
self.app.icon = "other"
self.app.icon = "other.icns"
self.assertEqual(self.app.icon.path, "other.icns")

def test_app_app_id(self):
Expand Down
2 changes: 2 additions & 0 deletions src/core/toga/command.py
Expand Up @@ -76,6 +76,8 @@ def enabled(self, value):
self._enabled = value
for widget in self._widgets:
widget.enabled = value
if self._impl is not None:
self._impl.enabled = value


GROUP_BREAK = object()
Expand Down
Binary file added src/core/toga/resources/tiberius.ico
Binary file not shown.
5 changes: 1 addition & 4 deletions src/core/toga/widgets/icon.py
Expand Up @@ -26,10 +26,7 @@ class Icon:
"""

def __init__(self, path, system=False):
if os.path.splitext(path)[1] in ('.png', '.icns', '.bmp'):
self.path = path
else:
self.path = path + '.icns'
self.path = path

self.system = system

Expand Down
56 changes: 47 additions & 9 deletions src/winforms/toga_winforms/app.py
@@ -1,4 +1,8 @@
from .libs import Threading, WinForms
import sys

import toga

from .libs import Threading, WinForms, add_handler
from .window import Window


Expand All @@ -17,21 +21,55 @@ def __init__(self, interface):
def create(self):
self.native = WinForms.Application

# self.native.setApplicationIconImage_(self.icon.native)

# Set the menu for the app.
# self.native.setMainMenu_(self.menu)
self.interface.commands.add(
toga.Command(None, 'About ' + self.interface.name, group=toga.Group.HELP),
toga.Command(None, 'Preferences', group=toga.Group.FILE),
# Quit should always be the last item, in a section on it's own
toga.Command(lambda s: self.exit(), 'Exit ' + self.interface.name, shortcut='q', group=toga.Group.FILE,
section=sys.maxsize),
toga.Command(None, 'Visit homepage', group=toga.Group.HELP)
)

# Call user code to populate the main window
self.interface.startup()
self._menu_items = {}
self.create_menus()
self.interface.main_window._impl.native.Icon = \
self.interface.icon.bind(self.interface.factory).native

def create_menus(self):
toga.Group.FILE.order = 0
# Only create the menu if the menu item index has been created.
if hasattr(self, '_menu_items'):
menubar = WinForms.MenuStrip()
submenu = None
for cmd in self.interface.commands:
if cmd == toga.GROUP_BREAK:
menubar.Items.Add(submenu)
submenu = None
elif cmd == toga.SECTION_BREAK:
submenu.DropDownItems.Add('-')
else:
if submenu is None:
submenu = WinForms.ToolStripMenuItem(cmd.group.label)
item = WinForms.ToolStripMenuItem(cmd.label)
if cmd.action:
item.Click += add_handler(cmd)
else:
item.Enabled = False
cmd._widgets.append(item)
self._menu_items[item] = cmd
submenu.DropDownItems.Add(item)
if submenu:
menubar.Items.Add(submenu)
self.interface.main_window._impl.native.Controls.Add(menubar)
self.interface.main_window._impl.native.MainMenuStrip = menubar
self.interface.main_window.content.refresh()

def open_document(self, fileURL):
'''Add a new document to this app.'''
print("STUB: If you want to handle opening documents, implement App.open_document(fileURL)")

def create_menus(self):
self.interface.factory.not_implemented('App.create_menus()')

def run_app(self):
self.create()
self.native.Run(self.interface.main_window._impl.native)
Expand All @@ -43,4 +81,4 @@ def main_loop(self):
thread.Join()

def exit(self):
self.interface.factory.not_implemented('App.exit()')
self.native.Exit()
16 changes: 10 additions & 6 deletions src/winforms/toga_winforms/command.py
@@ -1,10 +1,14 @@
#from .widgets.icon import Icon
from toga.widgets.icon import Icon as CoreIcon

class Command:
def __init__(self, interface):
self.interface = interface

# if self.interface.icon_id:
# self.icon = Icon.load(self.interface.icon_id)
# else:
# self.icon = None
self.native = None
if self.interface.icon_id:
# If icon_id is an icon, not a filepath
if type(self.interface.icon_id) is not str:
self.interface.icon = self.interface.icon_id
else:
self.interface.icon = CoreIcon(self.interface.icon_id)
else:
self.interface.icon = None
10 changes: 9 additions & 1 deletion src/winforms/toga_winforms/libs.py
Expand Up @@ -8,7 +8,8 @@
from System import Convert
from System import Threading
from System import Uri
from System.Drawing import Size, Point, Color, ContentAlignment
from System.Drawing import Size, Point, Color, ContentAlignment, Bitmap
from System.Drawing import Icon as WinIcon


def TextAlignment(value):
Expand All @@ -18,3 +19,10 @@ def TextAlignment(value):
CENTER: ContentAlignment.MiddleCenter,
JUSTIFY: ContentAlignment.MiddleLeft,
}[value]


def add_handler(cmd):
action = cmd.action
def handler(sender, event):
return action(None)
return handler
39 changes: 36 additions & 3 deletions src/winforms/toga_winforms/widgets/icon.py
@@ -1,8 +1,41 @@
# from ..libs import NSImage
import os

from toga import Icon as toga_Icon
from toga_winforms.libs import Bitmap, WinIcon


class Icon:
def __init__(self, interface):

def create_icon_from_file(filename):
icon_bitmap = Bitmap(self.interface.filename)
icon_handle = icon_bitmap.GetHicon()
return WinIcon.FromHandle(icon_handle)

self.interface = interface
interface._impl = self
# self.native = NSImage.alloc().initWithContentsOfFile(interface.filename)
self.interface._impl = self
valid_icon_extensions = ('.png', '.bmp', '.ico')
file_path, file_extension = os.path.splitext(self.interface.filename)

if file_extension == '.ico':
self.native = WinIcon(self.interface.filename)

elif os.path.isfile(file_path + '.ico'):
self.native = WinIcon(file_path + '.ico')

elif file_extension in valid_icon_extensions:
self.native = create_icon_from_file(self.interface.filename)

elif os.path.isfile(file_path + '.png'):
self.native = create_icon_from_file(file_path + '.png')

elif os.path.isfile(file_path + '.bmp'):
self.native = create_icon_from_file(file_path + '.bmp')

else:
print("[Winforms] No valid icon format available for {}; "
"fall back on Tiberius instead".format(
self.interface.filename))
tiberius_file = toga_Icon.TIBERIUS_ICON.filename + '.ico'
self.interface.icon = toga_Icon.TIBERIUS_ICON
self.native = WinIcon(tiberius_file)
2 changes: 1 addition & 1 deletion src/winforms/toga_winforms/widgets/webview.py
@@ -1,6 +1,6 @@
from travertino.size import at_least

from toga_winforms.libs import WinForms
from toga_winforms.libs import WinForms, Uri

from .base import Widget

Expand Down
26 changes: 20 additions & 6 deletions src/winforms/toga_winforms/window.py
@@ -1,7 +1,7 @@
from toga import GROUP_BREAK, SECTION_BREAK
from travertino.layout import Viewport

from .libs import WinForms, Size
from .libs import WinForms, Size, add_handler


class WinFormsViewport:
Expand Down Expand Up @@ -36,14 +36,21 @@ def create(self):
self.toolbar_items = None

def create_toolbar(self):
self.toolbar_native = WinForms.ToolStrip()
self.toolbar_native = WinForms.MenuStrip()
for cmd in self.interface.toolbar:
if cmd == GROUP_BREAK:
item = WinForms.ToolStripSeparator()
elif cmd == SECTION_BREAK:
item = WinForms.ToolStripSeparator()
else:
item = WinForms.ToolStripButton()
cmd.native = cmd.bind(self.interface.factory)
native_icon = cmd.icon.bind(self.interface.factory).native
if cmd.icon is not None:
item = WinForms.ToolStripMenuItem(cmd.label, native_icon.ToBitmap())
else:
item = WinForms.ToolStripMenuItem(cmd.label)

item.Click += add_handler(cmd)
self.toolbar_native.Items.Add(item)

def set_position(self, position):
Expand All @@ -58,15 +65,22 @@ def set_app(self, app):
@property
def vertical_shift(self):
# vertical shift is the toolbar height or 0
result = 0
try:
return self.native.interface._impl.toolbar_native.Height
result += self.native.interface._impl.toolbar_native.Height
except AttributeError:
return 0
pass
try:
result += self.native.interface._impl.native.MainMenuStrip.Height
except AttributeError:
pass
return result

def set_content(self, widget):
if self.toolbar_native:
self.native.Controls.Add(self.toolbar_native)

# Create the lookup table of menu items,
# then force the creation of the menus.
self.native.Controls.Add(widget.native)

# Set the widget's viewport to be based on the window's content.
Expand Down

0 comments on commit e8ed74c

Please sign in to comment.