├── tests └── __init__.py ├── toga_iOS ├── widgets │ ├── __init__.py │ ├── passwordinput.py │ ├── image.py │ ├── box.py │ ├── base.py │ ├── label.py │ ├── textinput.py │ ├── button.py │ ├── webview.py │ ├── imageview.py │ ├── navigationview.py │ └── list.py ├── libs │ ├── __init__.py │ ├── foundation.py │ ├── core_graphics.py │ └── uikit.py ├── font.py ├── window.py ├── __init__.py ├── app.py ├── dialogs.py └── container.py ├── MANIFEST.in ├── .gitignore ├── CONTRIBUTING.md ├── tox.ini ├── README.rst ├── LICENSE └── setup.py /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /toga_iOS/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /toga_iOS/libs/__init__.py: -------------------------------------------------------------------------------- 1 | from .core_graphics import * 2 | from .foundation import * 3 | from .uikit import * 4 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.rst 3 | include tox.ini 4 | recursive-include toga_iOS *.py 5 | recursive-include tests *.py -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | .*.sw[op] 4 | *.egg-info 5 | .coverage 6 | dist 7 | build 8 | _build 9 | distribute-* 10 | local 11 | .tox 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | PyBee <3's contributions! 4 | 5 | Please be aware, PyBee operates under a Code of Conduct. 6 | 7 | See [CONTRIBUTING to PyBee](http://pybee.org/contributing) for details. 8 | 9 | -------------------------------------------------------------------------------- /toga_iOS/font.py: -------------------------------------------------------------------------------- 1 | from toga.interface import Font as FontInterface 2 | from .libs import UIFont 3 | 4 | 5 | class Font(FontInterface): 6 | 7 | def create(self): 8 | self._impl = UIFont.fontWithName_size_(self.family, self.size) 9 | -------------------------------------------------------------------------------- /toga_iOS/widgets/passwordinput.py: -------------------------------------------------------------------------------- 1 | from .textinput import TextInput 2 | 3 | 4 | class PasswordInput(TextInput): 5 | def __init__(self, placeholder=None, style=None): 6 | super().__init__(placeholder=placeholder, style=style) 7 | 8 | def startup(self): 9 | super().startup() 10 | self._impl.setSecureTextEntry_(True) 11 | -------------------------------------------------------------------------------- /toga_iOS/widgets/image.py: -------------------------------------------------------------------------------- 1 | from ..libs import * 2 | 3 | 4 | class Image(object): 5 | def __init__(self, path): 6 | self.path = path 7 | 8 | if path.startswith('http://') or path.startswith('https://'): 9 | self._impl = UIImage.imageWithData_(NSData.dataWithContentsOfURL_(NSURL.URLWithString_(self.path))) 10 | else: 11 | self._impl = UIImage.alloc().initWithContentsOfFile_(self.path) 12 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (http://tox.testrun.org/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py26, py27, py33, py34 8 | 9 | [testenv] 10 | commands = {envpython} setup.py test 11 | deps = 12 | 13 | [testenv:py26] 14 | deps = 15 | unittest2 16 | -------------------------------------------------------------------------------- /toga_iOS/widgets/box.py: -------------------------------------------------------------------------------- 1 | from rubicon.objc import * 2 | 3 | from toga.interface import Box as BoxInterface 4 | 5 | from .base import WidgetMixin 6 | from ..libs import * 7 | 8 | 9 | class Box(BoxInterface, WidgetMixin): 10 | def __init__(self, id=None, style=None, children=None): 11 | super().__init__(id=id, style=style, children=children) 12 | self._create() 13 | 14 | def create(self): 15 | self._constraints = None -------------------------------------------------------------------------------- /toga_iOS/libs/foundation.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | from ctypes import util 3 | 4 | 5 | from rubicon.objc import * 6 | 7 | ###################################################################### 8 | 9 | # FOUNDATION 10 | 11 | foundation = cdll.LoadLibrary(util.find_library('Foundation')) 12 | 13 | foundation.NSMouseInRect.restype = c_bool 14 | foundation.NSMouseInRect.argtypes = [NSPoint, NSRect, c_bool] 15 | 16 | 17 | # NSArray.h 18 | 19 | NSMutableArray = ObjCClass('NSMutableArray') 20 | 21 | # NSData.h 22 | 23 | NSData = ObjCClass('NSData') 24 | 25 | # NSURL.h 26 | 27 | NSURL = ObjCClass('NSURL') 28 | 29 | # NSURLRequest.h 30 | 31 | NSURLRequest = ObjCClass('NSURLRequest') 32 | 33 | # UIFont.h 34 | 35 | UIFont = ObjCClass('UIFont') 36 | -------------------------------------------------------------------------------- /toga_iOS/libs/core_graphics.py: -------------------------------------------------------------------------------- 1 | # /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGImage.h 2 | kCGImageAlphaNone = 0 3 | kCGImageAlphaPremultipliedLast = 1 4 | kCGImageAlphaPremultipliedFirst = 2 5 | kCGImageAlphaLast = 3 6 | kCGImageAlphaFirst = 4 7 | kCGImageAlphaNoneSkipLast = 5 8 | kCGImageAlphaNoneSkipFirst = 6 9 | kCGImageAlphaOnly = 7 10 | 11 | kCGImageAlphaPremultipliedLast = 1 12 | 13 | kCGBitmapAlphaInfoMask = 0x1F 14 | kCGBitmapFloatComponents = 1 << 8 15 | 16 | kCGBitmapByteOrderMask = 0x7000 17 | kCGBitmapByteOrderDefault = 0 << 12 18 | kCGBitmapByteOrder16Little = 1 << 12 19 | kCGBitmapByteOrder32Little = 2 << 12 20 | kCGBitmapByteOrder16Big = 3 << 12 21 | kCGBitmapByteOrder32Big = 4 << 12 22 | -------------------------------------------------------------------------------- /toga_iOS/widgets/base.py: -------------------------------------------------------------------------------- 1 | from ..container import Constraints 2 | 3 | 4 | class WidgetMixin: 5 | def _set_app(self, app): 6 | pass 7 | 8 | def _set_window(self, window): 9 | pass 10 | 11 | def _set_container(self, container): 12 | if self._constraints and self._impl: 13 | self._container._impl.addSubview_(self._impl) 14 | self._constraints._container = container 15 | self.rehint() 16 | 17 | def _add_child(self, child): 18 | if self._container: 19 | child._set_container(self._container) 20 | 21 | def _add_constraints(self): 22 | self._impl.setTranslatesAutoresizingMaskIntoConstraints_(False) 23 | self._constraints = Constraints(self) 24 | 25 | def _apply_layout(self): 26 | if self._constraints: 27 | self._constraints.update() 28 | 29 | def rehint(self): 30 | pass 31 | 32 | def _set_font(self, font): 33 | self._impl.setFont_(font._impl) 34 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | toga-iOS 2 | ======== 3 | 4 | An iOS backend for the `Toga widget toolkit`_. 5 | 6 | **Toga requires Python 3** 7 | 8 | This package isn't much use by itself; it needs to be combined with `the core Toga library`_. 9 | 10 | For more details, see the `Toga project on Github`_. 11 | 12 | Community 13 | --------- 14 | 15 | Toga is part of the `BeeWare suite`_. You can talk to the community through: 16 | 17 | * `@pybeeware on Twitter`_ 18 | 19 | * The `pybee/general`_ channel on Gitter. 20 | 21 | Contributing 22 | ------------ 23 | 24 | If you experience problems with this backend, `log them on GitHub`_. If you 25 | want to contribute code, please `fork the code`_ and `submit a pull request`_. 26 | 27 | .. _Toga widget toolkit: http://pybee.org/toga 28 | .. _the core Toga library: https://github.com/pybee/toga-core 29 | .. _Toga project on Github: https://github.com/pybee/toga 30 | .. _BeeWare suite: http://pybee.org 31 | .. _@pybeeware on Twitter: https://twitter.com/pybeeware 32 | .. _pybee/general: https://gitter.im/pybee/general 33 | .. _log them on Github: https://github.com/pybee/toga-iOS/issues 34 | .. _fork the code: https://github.com/pybee/toga-iOS 35 | .. _submit a pull request: https://github.com/pybee/toga-iOS/pulls 36 | -------------------------------------------------------------------------------- /toga_iOS/widgets/label.py: -------------------------------------------------------------------------------- 1 | from toga.constants import LEFT_ALIGNED 2 | from toga.interface import Label as LabelInterface 3 | 4 | from .base import WidgetMixin 5 | from ..libs import UILabel, NSTextAlignment, NSLineBreakByWordWrapping, CGSize 6 | 7 | 8 | class Label(LabelInterface, WidgetMixin): 9 | def __init__(self, text, id=None, style=None, alignment=LEFT_ALIGNED): 10 | super().__init__(id=id, style=style, text=text, alignment=alignment) 11 | self._create() 12 | 13 | def create(self): 14 | self._impl = UILabel.new() 15 | self._impl._interface = self 16 | 17 | self._impl.setTranslatesAutoresizingMaskIntoConstraints_(False) 18 | self._impl.setLineBreakMode_(NSLineBreakByWordWrapping) 19 | 20 | # Add the layout constraints 21 | self._add_constraints() 22 | 23 | def _set_alignment(self, value): 24 | self._impl.setTextAlignment_(NSTextAlignment(value)) 25 | 26 | def _set_text(self, value): 27 | self._impl.setText_(value) 28 | 29 | def rehint(self): 30 | fitting_size = self._impl.systemLayoutSizeFittingSize_(CGSize(0, 0)) 31 | self.style.hint( 32 | height=fitting_size.height, 33 | width=(fitting_size.width, None) 34 | ) 35 | -------------------------------------------------------------------------------- /toga_iOS/widgets/textinput.py: -------------------------------------------------------------------------------- 1 | from toga.interface import TextInput as TextInputInterface 2 | 3 | from .base import WidgetMixin 4 | from ..libs import UITextField, UITextBorderStyleRoundedRect, CGSize 5 | 6 | 7 | class TextInput(TextInputInterface, WidgetMixin): 8 | _IMPL_CLASS = UITextField 9 | 10 | def __init__(self, id=None, style=None, initial=None, placeholder=None, readonly=False): 11 | super().__init__(id=id, style=style, initial=initial, placeholder=placeholder, readonly=readonly) 12 | self._create() 13 | 14 | def create(self): 15 | self._impl = self._IMPL_CLASS.new() 16 | self._impl._interface = self 17 | 18 | self._impl.setBorderStyle_(UITextBorderStyleRoundedRect) 19 | 20 | # Add the layout constraints 21 | self._add_constraints() 22 | 23 | def _set_readonly(self, value): 24 | self._impl.enabled = not value 25 | 26 | def _set_placeholder(self, value): 27 | self._impl.placeholder = self._placeholder 28 | 29 | def _get_value(self): 30 | return self._impl.text 31 | 32 | def _set_value(self, value): 33 | self._impl.text = value 34 | 35 | def rehint(self): 36 | # Height of a text input is known. 37 | fitting_size = self._impl.systemLayoutSizeFittingSize_(CGSize(0, 0)) 38 | self.style.hint( 39 | height=fitting_size.height, 40 | min_width=100 41 | ) 42 | -------------------------------------------------------------------------------- /toga_iOS/window.py: -------------------------------------------------------------------------------- 1 | from toga.interface.window import Window as WindowInterface 2 | 3 | from .container import Container 4 | from .libs import * 5 | from . import dialogs 6 | 7 | 8 | class Window(WindowInterface): 9 | _IMPL_CLASS = UIWindow 10 | _CONTAINER_CLASS = Container 11 | _DIALOG_MODULE = dialogs 12 | 13 | def __init__(self, title=None, position=(100, 100), size=(640, 480), toolbar=None, resizeable=True, closeable=True, minimizable=True): 14 | super().__init__(title=None, position=(100, 100), size=(640, 480), toolbar=None, resizeable=True, closeable=False, minimizable=False) 15 | self._create() 16 | 17 | def create(self): 18 | self._screen = UIScreen.mainScreen() 19 | self._impl = self._IMPL_CLASS.alloc().initWithFrame_(self._screen.bounds) 20 | self._impl._interface = self 21 | 22 | self._controller = UIViewController.alloc().init() 23 | self._impl.rootViewController = self._controller 24 | 25 | def _set_content(self, widget): 26 | self._controller.view = self._container._impl 27 | 28 | def _set_title(self, title): 29 | pass 30 | 31 | def show(self): 32 | self._impl.makeKeyAndVisible() 33 | 34 | # self._impl.visualizeConstraints_(self._impl.contentView().constraints()) 35 | # Do the first layout render. 36 | self.content._update_layout( 37 | width=self._screen.bounds.size.width, 38 | height=self._screen.bounds.size.height 39 | ) 40 | -------------------------------------------------------------------------------- /toga_iOS/widgets/button.py: -------------------------------------------------------------------------------- 1 | from rubicon.objc import objc_method 2 | 3 | from toga.interface import Button as ButtonInterface 4 | 5 | from .base import WidgetMixin 6 | from ..libs import * 7 | # from ..utils import process_callback 8 | 9 | 10 | class TogaButton(UIButton): 11 | @objc_method 12 | def onPress_(self, obj) -> None: 13 | if self._interface.on_press: 14 | # process_callback(self._interface.on_press(self._interface)) 15 | self._interface.on_press(self._interface) 16 | 17 | 18 | class Button(ButtonInterface, WidgetMixin): 19 | def __init__(self, label, id=None, on_press=None, style=None): 20 | super().__init__(label, id=id, style=style, on_press=on_press) 21 | self._create() 22 | 23 | def create(self): 24 | self._impl = TogaButton.alloc().init() 25 | self._impl._interface = self 26 | 27 | self._impl.setTitleColor_forState_(self._impl.tintColor, UIControlStateNormal) 28 | self._impl.addTarget_action_forControlEvents_(self._impl, get_selector('onPress:'), UIControlEventTouchDown) 29 | 30 | # Add the layout constraints 31 | self._add_constraints() 32 | 33 | def _set_label(self, value): 34 | self._impl.setTitle_forState_(value, UIControlStateNormal) 35 | 36 | def rehint(self): 37 | fitting_size = self._impl.systemLayoutSizeFittingSize_(CGSize(0, 0)) 38 | self.style.hint( 39 | height=fitting_size.height, 40 | min_width=fitting_size.width, 41 | ) 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Russell Keith-Magee. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of Toga nor the names of its contributors may 15 | be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /toga_iOS/widgets/webview.py: -------------------------------------------------------------------------------- 1 | from rubicon.objc import objc_method 2 | 3 | from toga.interface import WebView as WebViewInterface 4 | 5 | from .base import WidgetMixin 6 | from ..libs import * 7 | 8 | 9 | class TogaWebView(UIWebView): 10 | @objc_method 11 | def webView_didFinishLoadForFrame_(self, sender, frame) -> None: 12 | # print ("FINISHED LOADING") 13 | pass 14 | 15 | @objc_method 16 | def acceptsFirstResponder(self) -> bool: 17 | return True 18 | 19 | @objc_method 20 | def keyDown_(self, event) -> None: 21 | if self._interface.on_key_down: 22 | self._interface.on_key_down(event.keyCode, event.modifierFlags) 23 | 24 | 25 | class WebView(WebViewInterface, WidgetMixin): 26 | def __init__(self, id=None, style=None, url=None, on_key_down=None): 27 | super().__init__(id=id, style=style, url=url, on_key_down=on_key_down) 28 | self._create() 29 | 30 | def create(self): 31 | self._impl = TogaWebView.alloc().init() 32 | self._impl._interface = self 33 | 34 | self._impl.delegate = self._impl 35 | 36 | # Add the layout constraints 37 | self._add_constraints() 38 | 39 | def _set_url(self, value): 40 | if value: 41 | request = NSURLRequest.requestWithURL_(NSURL.URLWithString_(self._url)) 42 | self._impl.loadRequest_(request) 43 | 44 | def _set_content(self, root_url, content): 45 | self._impl.loadHTMLString_baseURL_(content, NSURL.URLWithString_(root_url)) 46 | 47 | def evaluate(self, javascript): 48 | return self._impl.stringByEvaluatingJavaScriptFromString_(javascript) 49 | -------------------------------------------------------------------------------- /toga_iOS/widgets/imageview.py: -------------------------------------------------------------------------------- 1 | from ..libs import * 2 | from .base import Widget 3 | from toga.constants import * 4 | 5 | 6 | class ImageView(Widget): 7 | def __init__(self, image=None, style=None): 8 | super().__init__(style=style) 9 | 10 | self.startup() 11 | 12 | self.image = image 13 | 14 | def startup(self): 15 | self._impl = UIImageView.alloc().init() 16 | self._impl.interface = self 17 | 18 | # Disable all autolayout functionality 19 | self._impl.setTranslatesAutoresizingMaskIntoConstraints_(False) 20 | self._impl.setAutoresizesSubviews_(False) 21 | 22 | # if self.width is None: 23 | # self.width = self._impl.fittingSize().width 24 | # if self.height is None: 25 | # self.height = self._impl.fittingSize().height 26 | 27 | # @property 28 | # def alignment(self): 29 | # return self._alignment 30 | 31 | # @alignment.setter 32 | # def alignment(self, value): 33 | # self._alignment = value 34 | # self._impl.setAlignment_(NSTextAlignment(self._alignment)) 35 | 36 | # @property 37 | # def scaling(self): 38 | # return self._scaling 39 | 40 | # @scaling.setter 41 | # def scaling(self, value): 42 | # self._scaling = value 43 | # self._impl.setAlignment_(NSTextAlignment(self._scaling)) 44 | 45 | @property 46 | def image(self): 47 | return self._impl.image 48 | 49 | @image.setter 50 | def image(self, image): 51 | if image: 52 | self._impl.image = image._impl 53 | 54 | def _set_frame(self, frame): 55 | print("SET IMAGE FRAME", self, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height) 56 | self._impl.setFrame_(frame) 57 | self._impl.setNeedsDisplay() 58 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/env python 2 | import io 3 | import re 4 | from setuptools import setup, find_packages 5 | import sys 6 | 7 | 8 | if sys.version_info[:3] < (3, 4): 9 | raise SystemExit("Toga requires Python 3.4+.") 10 | 11 | 12 | with io.open('./toga_iOS/__init__.py', encoding='utf8') as version_file: 13 | version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file.read(), re.M) 14 | if version_match: 15 | version = version_match.group(1) 16 | else: 17 | raise RuntimeError("Unable to find version string.") 18 | 19 | 20 | with io.open('README.rst', encoding='utf8') as readme: 21 | long_description = readme.read() 22 | 23 | 24 | setup( 25 | name='toga-iOS', 26 | version=version, 27 | description='An iOS backend for the Toga widget toolkit.', 28 | long_description=long_description, 29 | author='Russell Keith-Magee', 30 | author_email='russell@keith-magee.com', 31 | url='http://pybee.org/toga', 32 | packages=find_packages(exclude=['tests']), 33 | install_requires=[ 34 | 'rubicon-objc>=0.2.2', 35 | 'toga-core>=%s' % version, 36 | ], 37 | license='New BSD', 38 | classifiers=[ 39 | 'Development Status :: 3 - Alpha', 40 | 'Intended Audience :: Developers', 41 | 'License :: OSI Approved :: BSD License', 42 | 'Environment :: Handhelds/PDA\'s', 43 | 'Operating System :: iOS ', 44 | 'Programming Language :: Python :: 3', 45 | 'Programming Language :: Python :: 3.4', 46 | 'Programming Language :: Python :: 3.5', 47 | 'Programming Language :: Python :: 3 :: Only', 48 | 'Topic :: Software Development', 49 | 'Topic :: Software Development :: User Interfaces', 50 | 'Topic :: Software Development :: Widget Sets', 51 | ], 52 | test_suite='tests', 53 | ) 54 | -------------------------------------------------------------------------------- /toga_iOS/__init__.py: -------------------------------------------------------------------------------- 1 | # Core capabilities 2 | from .app import * 3 | from .window import * 4 | # from .command import * 5 | 6 | # Font support 7 | from .font import Font 8 | 9 | # # Widgets 10 | from .widgets.box import * 11 | from .widgets.button import * 12 | # # from .widgets.icon import * 13 | # from .widgets.image import * 14 | # from .widgets.imageview import * 15 | from .widgets.label import * 16 | from .widgets.list import * 17 | # from .widgets.multilinetextinput import * 18 | # from .widgets.optioncontainer import * 19 | from .widgets.navigationview import * 20 | # from .widgets.passwordinput import * 21 | # from .widgets.progressbar import * 22 | # from .widgets.scrollcontainer import * 23 | # from .widgets.splitcontainer import * 24 | # from .widgets.table import * 25 | from .widgets.textinput import * 26 | # from .widgets.tree import * 27 | from .widgets.webview import * 28 | 29 | __all__ = [ 30 | '__version__', 31 | 'App', 'MainWindow', 32 | 'Window', 33 | # 'Command', 'SEPARATOR', 'SPACER', 'EXPANDING_SPACER', 34 | 'Box', 35 | 'Button', 36 | # 'Icon', 'TIBERIUS_ICON', 37 | 'Font', 38 | # 'Image', 39 | # 'ImageView', 40 | 'List', 41 | 'Label', 42 | # 'MultilineTextInput', 43 | # 'OptionContainer', 44 | 'NavigationView', 45 | # 'PasswordInput', 46 | # 'ProgressBar', 47 | # 'ScrollContainer', 48 | # 'SplitContainer', 49 | # 'Table', 50 | 'TextInput', 51 | # 'Tree', 52 | 'WebView', 53 | ] 54 | 55 | # Examples of valid version strings 56 | # __version__ = '1.2.3.dev1' # Development release 1 57 | # __version__ = '1.2.3a1' # Alpha Release 1 58 | # __version__ = '1.2.3b1' # Beta Release 1 59 | # __version__ = '1.2.3rc1' # RC Release 1 60 | # __version__ = '1.2.3' # Final Release 61 | # __version__ = '1.2.3.post1' # Post Release 1 62 | 63 | __version__ = '0.2.4' 64 | -------------------------------------------------------------------------------- /toga_iOS/app.py: -------------------------------------------------------------------------------- 1 | from rubicon.objc import objc_method 2 | 3 | from toga.interface.app import App as AppInterface 4 | 5 | from .libs import * 6 | from .window import Window 7 | 8 | 9 | class MainWindow(Window): 10 | def __init__(self, title=None, position=(100, 100), size=(640, 480)): 11 | super().__init__(title, position, size) 12 | 13 | def startup(self): 14 | super(MainWindow, self).startup() 15 | self._impl.setBackgroundColor_(UIColor.whiteColor()) 16 | 17 | 18 | class PythonAppDelegate(UIResponder): 19 | @objc_method 20 | def applicationDidBecomeActive(self) -> None: 21 | print("App became active.") 22 | 23 | @objc_method 24 | def application_didFinishLaunchingWithOptions_(self, application, launchOptions) -> bool: 25 | print("App finished launching.") 26 | App.app._startup() 27 | return True 28 | 29 | @objc_method 30 | def application_didChangeStatusBarOrientation_(self, application, oldStatusBarOrientation: int) -> None: 31 | print("ROTATED", oldStatusBarOrientation) 32 | App.app.main_window.content._update_layout( 33 | width=App.app.main_window._screen.bounds.size.width, 34 | height=App.app.main_window._screen.bounds.size.height, 35 | ) 36 | 37 | 38 | class App(AppInterface): 39 | _MAIN_WINDOW_CLASS = MainWindow 40 | 41 | def __init__(self, name, app_id, startup=None, document_types=None): 42 | super().__init__( 43 | name=name, 44 | app_id=app_id, 45 | icon=None, 46 | startup=startup, 47 | document_types=document_types 48 | ) 49 | 50 | def _startup(self): 51 | self.startup() 52 | 53 | def main_loop(self): 54 | # Main loop is a no-op on iOS; the app loop is integrated with the 55 | # main iOS event loop. 56 | pass 57 | -------------------------------------------------------------------------------- /toga_iOS/widgets/navigationview.py: -------------------------------------------------------------------------------- 1 | from rubicon.objc import * 2 | 3 | from ..libs import * 4 | from .base import WidgetMixin 5 | 6 | 7 | def button_for_action(callback): 8 | # if callback.icon == ... 9 | return UIBarButtonSystemItemAdd 10 | 11 | 12 | class TogaNavigationController(UINavigationController): 13 | # @objc_method 14 | # def viewDidAppear_(self, animated: bool) -> None: 15 | # print("VIEW APPEARED", animated) 16 | # self.interface._update_layout() 17 | 18 | @objc_method 19 | def onAction(self): 20 | if self.interface.on_action: 21 | self.interface.on_action(self.interface) 22 | 23 | 24 | class NavigationView(WidgetMixin): 25 | def __init__(self, title, content, on_action=None, style=None): 26 | super().__init__(style=style) 27 | self.title = title 28 | self.content = content 29 | self.on_action = on_action 30 | 31 | self.startup() 32 | 33 | def startup(self): 34 | self._impl = TogaNavigationController.alloc().initWithRootViewController_(self.content._impl) 35 | self._impl.interface = self 36 | self._impl.navigationBar.topItem.title = self.title 37 | 38 | if self.on_action: 39 | self._action_button = UIBarButtonItem.alloc().initWithBarButtonSystemItem_target_action_( 40 | button_for_action(self.on_action), 41 | self._impl, 42 | get_selector('onAction') 43 | ) 44 | self._impl.navigationBar.topItem.rightBarButtonItem = self._action_button 45 | 46 | def _set_app(self, app): 47 | self.content.app = app 48 | 49 | def _set_window(self, window): 50 | self.content.window = window 51 | 52 | def _set_frame(self, frame): 53 | # print("SET FRAME", self, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height) 54 | # self._impl.setFrame_(frame) 55 | # self._impl.setNeedsDisplay() 56 | pass 57 | -------------------------------------------------------------------------------- /toga_iOS/dialogs.py: -------------------------------------------------------------------------------- 1 | from rubicon.objc import * 2 | 3 | from .libs import * 4 | from .widgets.base import WidgetMixin 5 | 6 | 7 | class TogaDialog(UIViewController): 8 | @objc_method 9 | def loadView(self) -> None: 10 | self.title = self.interface.title 11 | 12 | self.cancelButton = UIBarButtonItem.alloc().initWithBarButtonSystemItem_target_action_( 13 | UIBarButtonSystemItemCancel, 14 | self, 15 | get_selector('cancelClicked') 16 | ) 17 | self.navigationController.navigationBar.topItem.leftBarButtonItem = self.cancelButton 18 | 19 | self.doneButton = UIBarButtonItem.alloc().initWithBarButtonSystemItem_target_action_( 20 | UIBarButtonSystemItemDone, 21 | self, 22 | get_selector('doneClicked') 23 | ) 24 | self.navigationController.navigationBar.topItem.rightBarButtonItem = self.doneButton 25 | 26 | self.interface.content._update_layout( 27 | width=UIScreen.mainScreen().bounds.size.width, 28 | height=UIScreen.mainScreen().bounds.size.height, 29 | padding_top=12 30 | ) 31 | 32 | self.view = self.interface.content._impl 33 | 34 | @objc_method 35 | def cancelClicked(self): 36 | self.dismissModalViewControllerAnimated_(True) 37 | if self.interface.on_cancel: 38 | self.interface.on_cancel(self.interface) 39 | 40 | @objc_method 41 | def doneClicked(self): 42 | self.dismissModalViewControllerAnimated_(True) 43 | if self.interface.on_accept: 44 | self.interface.on_accept(self.interface) 45 | 46 | 47 | class Dialog: 48 | def __init__(self, title, content, on_accept=None, on_cancel=None): 49 | self.title = title 50 | self.content = content 51 | 52 | self.on_accept = on_accept 53 | self.on_cancel = on_cancel 54 | 55 | self.startup() 56 | 57 | def startup(self): 58 | self.content.startup() 59 | self._impl = TogaDialog.alloc().init() 60 | self._impl.interface = self 61 | -------------------------------------------------------------------------------- /toga_iOS/widgets/list.py: -------------------------------------------------------------------------------- 1 | from rubicon.objc import objc_method 2 | 3 | from .base import WidgetMixin 4 | from ..libs import * 5 | # from ..utils import process_callback 6 | 7 | 8 | class TogaTableViewController(UITableViewController): 9 | @objc_method 10 | def numberOfSectionsInTableView_(self) -> int: 11 | return 1 12 | 13 | @objc_method 14 | def tableView_numberOfRowsInSection_(self, tableView, section: int) -> int: 15 | return len(self.data) 16 | 17 | @objc_method 18 | def tableView_cellForRowAtIndexPath_(self, tableView, indexPath): 19 | cell = tableView.dequeueReusableCellWithIdentifier_("row") 20 | if cell is None: 21 | cell = UITableViewCell.alloc().initWithStyle_reuseIdentifier_(UITableViewCellStyleDefault, "row") 22 | 23 | cell.textLabel.text = self.interface.data[indexPath.item]['description'] 24 | return cell 25 | 26 | @objc_method 27 | def tableView_commitEditingStyle_forRowAtIndexPath_(self, tableView, editingStyle: int, indexPath): 28 | if editingStyle == UITableViewCellEditingStyleDelete: 29 | item = self.data[indexPath.row] 30 | 31 | if self.interface.on_delete: 32 | self.interface.on_delete(self.interface) 33 | 34 | del self.data[indexPath.row] 35 | 36 | paths = NSArray.alloc().initWithObjects_(indexPath, None) 37 | tableView.deleteRowsAtIndexPaths_withRowAnimation_(paths, UITableViewRowAnimationFade) 38 | 39 | @objc_method 40 | def refresh(self): 41 | if self.interface.on_refresh: 42 | self.interface.on_refresh(self.interface) 43 | self.refreshControl.endRefreshing() 44 | self.tableView.reloadData() 45 | 46 | 47 | class List(WidgetMixin): 48 | def __init__(self, data=None, on_delete=None, on_refresh=None, style=None): 49 | super().__init__(style=style) 50 | self.data = data 51 | self.on_delete = on_delete 52 | self.on_refresh = on_refresh 53 | 54 | self.startup() 55 | 56 | def startup(self): 57 | self._impl = TogaTableViewController.alloc().init() 58 | self._impl.interface = self 59 | 60 | self._impl.refreshControl = UIRefreshControl.alloc().init() 61 | self._impl.refreshControl.addTarget_action_forControlEvents_( 62 | self._impl, 63 | get_selector('refresh'), 64 | UIControlEventValueChanged 65 | ) 66 | 67 | self._impl.data = self.data 68 | 69 | def add(self, item): 70 | self.data.append(item) 71 | self._impl.tableView.reloadData() 72 | -------------------------------------------------------------------------------- /toga_iOS/container.py: -------------------------------------------------------------------------------- 1 | from .libs import ( 2 | objc_method, 3 | NSLayoutAttributeTop, NSLayoutAttributeLeft, 4 | NSLayoutAttributeRight, NSLayoutAttributeBottom, 5 | NSLayoutRelationEqual, NSLayoutRelationGreaterThanOrEqual, NSLayoutRelationLessThanOrEqual, 6 | NSLayoutConstraint, 7 | NSLayoutPriority, 8 | NSRect, NSPoint, NSSize, 9 | UIView, UIColor 10 | ) 11 | 12 | 13 | class Constraints: 14 | def __init__(self, widget): 15 | self.widget = widget 16 | self.__container = None 17 | 18 | self._width_constraint = None 19 | self._height_constraint = None 20 | 21 | self._left_constraint = None 22 | self._top_constraint = None 23 | 24 | @property 25 | def widget(self): 26 | return self._widget 27 | 28 | @widget.setter 29 | def widget(self, value): 30 | self._widget = value 31 | 32 | @property 33 | def _container(self): 34 | return self.__container 35 | 36 | @_container.setter 37 | def _container(self, value): 38 | self.__container = value 39 | # print("Add constraints for", self._widget, 'in', self._container, self._widget.style.layout) 40 | self._left_constraint = NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_( 41 | self._widget._impl, NSLayoutAttributeLeft, 42 | NSLayoutRelationEqual, 43 | self._container._impl, NSLayoutAttributeLeft, 44 | 1.0, self._widget.style.layout.absolute.left 45 | ) 46 | self._container._impl.addConstraint_(self._left_constraint) 47 | 48 | self._top_constraint = NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_( 49 | self._widget._impl, NSLayoutAttributeTop, 50 | NSLayoutRelationEqual, 51 | self._container._impl, NSLayoutAttributeTop, 52 | 1.0, self._widget.style.layout.absolute.top 53 | ) 54 | self._container._impl.addConstraint_(self._top_constraint) 55 | 56 | self._width_constraint = NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_( 57 | self._widget._impl, NSLayoutAttributeRight, 58 | NSLayoutRelationEqual, 59 | self._widget._impl, NSLayoutAttributeLeft, 60 | 1.0, self._widget.style.layout.width 61 | ) 62 | self._container._impl.addConstraint_(self._width_constraint) 63 | 64 | self._height_constraint = NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_( 65 | self._widget._impl, NSLayoutAttributeBottom, 66 | NSLayoutRelationEqual, 67 | self._widget._impl, NSLayoutAttributeTop, 68 | 1.0, self._widget.style.layout.height 69 | ) 70 | self._container._impl.addConstraint_(self._height_constraint) 71 | 72 | def make_root(self): 73 | self.__container = None 74 | # print("Make ", self._widget, 'a root container') 75 | self._height_constraint = NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_( 76 | self._widget._impl, NSLayoutAttributeBottom, 77 | NSLayoutRelationEqual, 78 | self._widget._impl, NSLayoutAttributeTop, 79 | 1, 0, 80 | ) 81 | self._widget._impl.addConstraint_(self._height_constraint) 82 | 83 | self._width_constraint = NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_( 84 | self._widget._impl, NSLayoutAttributeRight, 85 | NSLayoutRelationEqual, 86 | self._widget._impl, NSLayoutAttributeLeft, 87 | 1, 0, 88 | ) 89 | self._widget._impl.addConstraint_(self._width_constraint) 90 | 91 | def update(self): 92 | # print("UPDATE", self._widget, 'in', self._container, 'to', self._widget.style.layout) 93 | if self._container: 94 | # print(" in", self._container) 95 | self.top = self._widget.style.layout.absolute.top 96 | self.left = self._widget.style.layout.absolute.left 97 | 98 | self.width = self._widget.style.layout.width 99 | self.height = self._widget.style.layout.height 100 | 101 | @property 102 | def width(self): 103 | if self._width_constraint: 104 | return self._width_constraint.constant 105 | 106 | @width.setter 107 | def width(self, value): 108 | if self._width_constraint: 109 | # print("SET WIDTH", self._widget, value) 110 | self._width_constraint.constant = value 111 | 112 | @property 113 | def height(self): 114 | if self._height_constraint: 115 | return self._height_constraint.constant 116 | 117 | @height.setter 118 | def height(self, value): 119 | if self._height_constraint: 120 | # print("SET HEIGHT", self._widget, value) 121 | self._height_constraint.constant = value 122 | 123 | @property 124 | def left(self): 125 | if self._left_constraint: 126 | return self._left_constraint.constant 127 | 128 | @left.setter 129 | def left(self, value): 130 | if self._left_constraint: 131 | # print("SET LEFT", self._widget, value) 132 | self._left_constraint.constant = value 133 | 134 | @property 135 | def top(self): 136 | if self._top_constraint: 137 | return self._top_constraint.constant 138 | 139 | @top.setter 140 | def top(self, value): 141 | if self._top_constraint: 142 | # print("SET TOP", self._widget, value) 143 | self._top_constraint.constant = value 144 | 145 | 146 | class TogaContainer(UIView): 147 | @objc_method 148 | def isFlipped(self) -> bool: 149 | # Default Cocoa coordinate frame is around the wrong way. 150 | return True 151 | 152 | @objc_method 153 | def display(self) -> None: 154 | self.layer.setNeedsDisplay_(True) 155 | self.layer.displayIfNeeded() 156 | 157 | 158 | class Container: 159 | def __init__(self): 160 | self._impl = TogaContainer.alloc().init() 161 | self._impl.setTranslatesAutoresizingMaskIntoConstraints_(False) 162 | self._impl.setBackgroundColor_(UIColor.whiteColor()) 163 | 164 | self._content = None 165 | self._constraints = Constraints(self) 166 | 167 | @property 168 | def content(self): 169 | return self._content 170 | 171 | @content.setter 172 | def content(self, widget): 173 | self._content = widget 174 | self._content._container = self 175 | 176 | @property 177 | def root_content(self): 178 | return self._content 179 | 180 | @root_content.setter 181 | def root_content(self, widget): 182 | self._content = widget 183 | self._content._container = self 184 | # Make the constraints object a root container. 185 | self._constraints.make_root() 186 | 187 | def _update_layout(self, **style): 188 | if self._content: 189 | self._constraints.width = self._content.style.layout.width 190 | self._constraints.height = self._content.style.layout.height 191 | 192 | self._content._update_layout(**style) 193 | -------------------------------------------------------------------------------- /toga_iOS/libs/uikit.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | from ctypes import util 3 | from enum import Enum 4 | 5 | from rubicon.objc import * 6 | 7 | from toga.constants import * 8 | 9 | ###################################################################### 10 | 11 | # UIKit 12 | 13 | uikit = cdll.LoadLibrary(util.find_library('UIKit')) 14 | 15 | uikit.UIApplicationMain.restype = c_int 16 | uikit.UIApplicationMain.argtypes = [c_int, POINTER(c_char_p), c_void_p, c_void_p] 17 | 18 | NSArray = ObjCClass('NSArray') 19 | NSMutableArray = ObjCClass('NSMutableArray') 20 | 21 | # NSLayoutConstraint.h 22 | NSLayoutConstraint = ObjCClass('NSLayoutConstraint') 23 | 24 | NSLayoutRelationLessThanOrEqual = -1 25 | NSLayoutRelationEqual = 0 26 | NSLayoutRelationGreaterThanOrEqual = 1 27 | 28 | NSLayoutAttributeLeft = 1 29 | NSLayoutAttributeRight = 2 30 | NSLayoutAttributeTop = 3 31 | NSLayoutAttributeBottom = 4 32 | NSLayoutAttributeLeading = 5 33 | NSLayoutAttributeTrailing = 6 34 | NSLayoutAttributeWidth = 7 35 | NSLayoutAttributeHeight = 8 36 | NSLayoutAttributeCenterX = 9 37 | NSLayoutAttributeCenterY = 10 38 | NSLayoutAttributeBaseline = 11 39 | 40 | NSLayoutAttributeNotAnAttribute = 0 41 | 42 | NSLayoutFormatAlignAllLeft = (1 << NSLayoutAttributeLeft) 43 | NSLayoutFormatAlignAllRight = (1 << NSLayoutAttributeRight) 44 | NSLayoutFormatAlignAllTop = (1 << NSLayoutAttributeTop) 45 | NSLayoutFormatAlignAllBottom = (1 << NSLayoutAttributeBottom) 46 | NSLayoutFormatAlignAllLeading = (1 << NSLayoutAttributeLeading) 47 | NSLayoutFormatAlignAllTrailing = (1 << NSLayoutAttributeTrailing) 48 | NSLayoutFormatAlignAllCenterX = (1 << NSLayoutAttributeCenterX) 49 | NSLayoutFormatAlignAllCenterY = (1 << NSLayoutAttributeCenterY) 50 | NSLayoutFormatAlignAllBaseline = (1 << NSLayoutAttributeBaseline) 51 | 52 | NSLayoutFormatAlignmentMask = 0xFFFF 53 | 54 | NSLayoutFormatDirectionLeadingToTrailing = 0 << 16 55 | NSLayoutFormatDirectionLeftToRight = 1 << 16 56 | NSLayoutFormatDirectionRightToLeft = 2 << 16 57 | 58 | NSLayoutFormatDirectionMask = 0x3 << 16 59 | 60 | NSLayoutConstraintOrientationHorizontal = 0, 61 | NSLayoutConstraintOrientationVertical = 1 62 | 63 | class NSEdgetInsets(Structure): 64 | _fields_ = [ 65 | ("top", CGFloat), 66 | ("left", CGFloat), 67 | ("bottom", CGFloat), 68 | ("right", CGFloat), 69 | ] 70 | 71 | def NSEdgeInsetsMake(top, left, bottom, right): 72 | return NSEdgeInsets(top, left, bottom, right) 73 | 74 | 75 | class NSLayoutPriority(Enum): 76 | Required = 1000 77 | DefaultHigh = 750 78 | DragThatCanResizeWindow = 510 79 | WindowSizeStayPut = 500 80 | DragThatCannotResizeWindow = 490 81 | DefaultLow = 250 82 | FittingSizeCompression = 50 83 | 84 | # NSText.h 85 | NSLeftTextAlignment = 0 86 | NSRightTextAlignment = 1 87 | NSCenterTextAlignment = 2 88 | NSJustifiedTextAlignment = 3 89 | NSNaturalTextAlignment = 4 90 | 91 | def NSTextAlignment(alignment): 92 | return { 93 | LEFT_ALIGNED: NSLeftTextAlignment, 94 | RIGHT_ALIGNED: NSRightTextAlignment, 95 | CENTER_ALIGNED: NSCenterTextAlignment, 96 | JUSTIFIED_ALIGNED: NSJustifiedTextAlignment, 97 | NATURAL_ALIGNED: NSNaturalTextAlignment, 98 | }[alignment] 99 | 100 | # UIControl.h 101 | 102 | # UIControlEvents 103 | UIControlEventTouchDown = 1 << 0 104 | UIControlEventTouchDownRepeat = 1 << 1 105 | UIControlEventTouchDragInside = 1 << 2 106 | UIControlEventTouchDragOutside = 1 << 3 107 | UIControlEventTouchDragEnter = 1 << 4 108 | UIControlEventTouchDragExit = 1 << 5 109 | UIControlEventTouchUpInside = 1 << 6 110 | UIControlEventTouchUpOutside = 1 << 7 111 | UIControlEventTouchCancel = 1 << 8 112 | 113 | UIControlEventValueChanged = 1 << 12 114 | 115 | UIControlEventEditingDidBegin = 1 << 16 116 | UIControlEventEditingChanged = 1 << 17 117 | UIControlEventEditingDidEnd = 1 << 18 118 | UIControlEventEditingDidEndOnExit = 1 << 19 119 | 120 | UIControlEventAllTouchEvents = 0x00000FFF 121 | UIControlEventAllEditingEvents = 0x000F0000 122 | UIControlEventApplicationReserved = 0x0F000000 123 | UIControlEventSystemReserved = 0xF0000000 124 | UIControlEventAllEvents = 0xFFFFFFFF 125 | 126 | # UIControlContentVerticalAlignment 127 | UIControlContentVerticalAlignmentCenter = 0 128 | UIControlContentVerticalAlignmentTop = 1 129 | UIControlContentVerticalAlignmentBottom = 2 130 | UIControlContentVerticalAlignmentFill = 3 131 | 132 | # UIControlContentHorizontalAlignment 133 | UIControlContentHorizontalAlignmentCenter = 0 134 | UIControlContentHorizontalAlignmentLeft = 1 135 | UIControlContentHorizontalAlignmentRight = 2 136 | UIControlContentHorizontalAlignmentFill = 3 137 | 138 | # UIControlState 139 | UIControlStateNormal = 0 140 | UIControlStateHighlighted = 1 << 0 141 | UIControlStateDisabled = 1 << 1 142 | UIControlStateSelected = 1 << 2 143 | UIControlStateApplication = 0x00FF0000 144 | UIControlStateReserved = 0xFF000000 145 | 146 | # UIImage.h 147 | UIImage = ObjCClass('UIImage') 148 | 149 | # UIImageView.h 150 | UIImageView = ObjCClass('UIImageView') 151 | 152 | # UIResponder.h 153 | UIResponder = ObjCClass('UIResponder') 154 | 155 | # UIWindow.h 156 | UIWindow = ObjCClass('UIWindow') 157 | 158 | # UIWindow.h 159 | UIWindow = ObjCClass('UIWindow') 160 | 161 | # UIScreen.h 162 | UIScreen = ObjCClass('UIScreen') 163 | 164 | # UIColor.h 165 | UIColor = ObjCClass('UIColor') 166 | 167 | # UIView.h 168 | UIView = ObjCClass('UIView') 169 | 170 | # UIWindow.h 171 | UIWindow = ObjCClass('UIWindow') 172 | 173 | # UILabel.h 174 | NSLineBreakByWordWrapping = 0 175 | NSLineBreakByCharWrapping = 1 176 | NSLineBreakByClipping = 2 177 | NSLineBreakByTruncatingHead = 3 178 | NSLineBreakByTruncatingTail = 4 179 | NSLineBreakByTruncatingMiddle = 5 180 | 181 | UILabel = ObjCClass('UILabel') 182 | 183 | # UINavigationController.h 184 | UINavigationController = ObjCClass('UINavigationController') 185 | 186 | # UIButton.h 187 | UIButton = ObjCClass('UIButton') 188 | 189 | # UIBarButtonItem.h 190 | UIBarButtonItem = ObjCClass('UIBarButtonItem') 191 | 192 | UIBarButtonSystemItemDone = 0 193 | UIBarButtonSystemItemCancel = 1 194 | UIBarButtonSystemItemEdit = 2 195 | UIBarButtonSystemItemSave = 3 196 | UIBarButtonSystemItemAdd = 4 197 | UIBarButtonSystemItemFlexibleSpace = 5 198 | UIBarButtonSystemItemFixedSpace = 6 199 | UIBarButtonSystemItemCompose = 7 200 | UIBarButtonSystemItemReply = 8 201 | UIBarButtonSystemItemAction = 9 202 | UIBarButtonSystemItemOrganize = 10 203 | UIBarButtonSystemItemBookmarks = 11 204 | UIBarButtonSystemItemSearch = 12 205 | UIBarButtonSystemItemRefresh = 13 206 | UIBarButtonSystemItemStop = 14 207 | UIBarButtonSystemItemCamera = 15 208 | UIBarButtonSystemItemTrash = 16 209 | UIBarButtonSystemItemPlay = 17 210 | UIBarButtonSystemItemPause = 18 211 | UIBarButtonSystemItemRewind = 19 212 | UIBarButtonSystemItemFastForward = 20 213 | UIBarButtonSystemItemUndo = 21 214 | UIBarButtonSystemItemRedo = 22 215 | UIBarButtonSystemItemPageCurl = 23 216 | 217 | # UIViewController.h 218 | UIViewController = ObjCClass('UIViewController') 219 | 220 | # UIRefreshControl.h 221 | UIRefreshControl = ObjCClass('UIRefreshControl') 222 | 223 | # UITableView.h 224 | UITableView = ObjCClass('UITableView') 225 | UITableViewController = ObjCClass('UITableViewController') 226 | 227 | NSIndexPath = ObjCClass('NSIndexPath') 228 | 229 | UITableViewRowAnimationFade = 0 230 | UITableViewRowAnimationRight = 1 231 | UITableViewRowAnimationLeft = 2 232 | UITableViewRowAnimationTop = 3 233 | UITableViewRowAnimationBottom = 4 234 | UITableViewRowAnimationNone = 5 235 | UITableViewRowAnimationMiddle = 6 236 | UITableViewRowAnimationAutomatic = 100 237 | 238 | # UITableViewCell.h 239 | UITableViewCell = ObjCClass('UITableViewCell') 240 | 241 | UITableViewCellStyleDefault = 0 242 | UITableViewCellStyleValue1 = 1 243 | UITableViewCellStyleValue2 = 2 244 | UITableViewCellStyleSubtitle = 3 245 | 246 | UITableViewCellEditingStyleNone = 0 247 | UITableViewCellEditingStyleDelete = 1 248 | UITableViewCellEditingStyleInsert = 2 249 | 250 | # UITextField.h 251 | UITextField = ObjCClass('UITextField') 252 | 253 | UITextBorderStyleNone = 0 254 | UITextBorderStyleLine = 1 255 | UITextBorderStyleBezel = 2 256 | UITextBorderStyleRoundedRect = 3 257 | 258 | # UIWebView.h 259 | UIWebView = ObjCClass('UIWebView') 260 | --------------------------------------------------------------------------------