<s> import objc <EOL> import Foundation <EOL> import AppKit <EOL> from AppKit import NSApplication , NSStatusBar , NSMenu , NSMenuItem , NSAlert , NSTextField , NSImage <EOL> from Foundation import ( NSDate , NSTimer , NSRunLoop , NSDefaultRunLoopMode , <EOL> NSSearchPathForDirectoriesInDomains , NSMakeRect , NSLog , NSObject ) <EOL> from PyObjCTools import AppHelper <EOL> import os <EOL> import sys <EOL> import weakref <EOL> from collections import Mapping , Iterable <EOL> from . utils import ListDict <EOL> _TIMERS = weakref . WeakSet ( ) <EOL> separator = object ( ) <EOL> def debug_mode ( choice ) : <EOL> """<STR_LIT>""" <EOL> global _log <EOL> if choice : <EOL> def _log ( * args ) : <EOL> NSLog ( '<STR_LIT:U+0020>' . join ( map ( str , args ) ) ) <EOL> else : <EOL> def _log ( * _ ) : <EOL> pass <EOL> debug_mode ( False ) <EOL> def alert ( title , message = '<STR_LIT>' , ok = None , cancel = False ) : <EOL> """<STR_LIT>""" <EOL> message = str ( message ) <EOL> title = str ( title ) <EOL> alert = NSAlert . alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_ ( <EOL> title , ok , '<STR_LIT>' if cancel else None , None , message ) <EOL> alert . setAlertStyle_ ( <NUM_LIT:0> ) <EOL> _log ( '<STR_LIT>' . format ( repr ( message ) , repr ( title ) ) ) <EOL> return alert . runModal ( ) <EOL> def notification ( title , subtitle , message , data = None , sound = True ) : <EOL> """<STR_LIT>""" <EOL> """<STR_LIT>""" <EOL> pass <EOL> def application_support ( name ) : <EOL> """<STR_LIT>""" <EOL> app_support_path = os . path . join ( NSSearchPathForDirectoriesInDomains ( <NUM_LIT> , <NUM_LIT:1> , <NUM_LIT:1> ) . objectAtIndex_ ( <NUM_LIT:0> ) , name ) <EOL> if not os . path . isdir ( app_support_path ) : <EOL> os . mkdir ( app_support_path ) <EOL> return app_support_path <EOL> def timers ( ) : <EOL> """<STR_LIT>""" <EOL> return set ( _TIMERS ) <EOL> def _nsimage_from_file ( filename , dimensions = None ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> _log ( '<STR_LIT>' . format ( filename ) ) <EOL> with open ( filename ) : <EOL> pass <EOL> except IOError : <EOL> try : <EOL> from __main__ import __file__ as main_script_path <EOL> main_script_path = os . path . dirname ( main_script_path ) <EOL> filename = os . path . join ( main_script_path , filename ) <EOL> except ImportError : <EOL> pass <EOL> _log ( '<STR_LIT>' . format ( filename ) ) <EOL> with open ( filename ) : <EOL> pass <EOL> image = NSImage . alloc ( ) . initByReferencingFile_ ( filename ) <EOL> image . setScalesWhenResized_ ( True ) <EOL> image . setSize_ ( ( <NUM_LIT:20> , <NUM_LIT:20> ) if dimensions is None else dimensions ) <EOL> return image <EOL> def timer ( interval ) : <EOL> """<STR_LIT>""" <EOL> def decorator ( f ) : <EOL> timers = timer . __dict__ . setdefault ( '<STR_LIT>' , [ ] ) <EOL> timers . append ( Timer ( f , interval ) ) <EOL> return f <EOL> return decorator <EOL> def clicked ( * args ) : <EOL> """<STR_LIT>""" <EOL> def decorator ( f ) : <EOL> def register_click ( self ) : <EOL> menuitem = self . _menu <EOL> if menuitem is None : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> try : <EOL> for arg in args : <EOL> menuitem = menuitem [ arg ] <EOL> except KeyError : <EOL> raise ValueError ( '<STR_LIT>' . format ( '<STR_LIT>' . join ( map ( repr , args ) ) ) ) <EOL> menuitem . set_callback ( f ) <EOL> buttons = clicked . __dict__ . setdefault ( '<STR_LIT>' , [ ] ) <EOL> buttons . append ( register_click ) <EOL> return f <EOL> return decorator <EOL> def notifications ( f ) : <EOL> """<STR_LIT>""" <EOL> notifications . __dict__ [ '<STR_LIT>' ] = f <EOL> return f <EOL> def _call_as_function_or_method ( f , event ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> r = f ( event ) <EOL> _log ( '<STR_LIT>' . format ( repr ( f ) ) ) <EOL> return r <EOL> except TypeError as e : <EOL> if e . message . endswith ( '<STR_LIT>' ) : <EOL> r = f ( getattr ( App , '<STR_LIT>' ) , event ) <EOL> _log ( '<STR_LIT>' . format ( repr ( f ) ) ) <EOL> return r <EOL> raise e <EOL> class Menu ( ListDict ) : <EOL> """<STR_LIT>""" <EOL> _choose_key = object ( ) <EOL> def __init__ ( self ) : <EOL> self . _separators = <NUM_LIT:1> <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _menu = NSMenu . alloc ( ) . init ( ) <EOL> super ( Menu , self ) . __init__ ( ) <EOL> def __setitem__ ( self , key , value ) : <EOL> if key not in self : <EOL> key , value = self . _process_new_menuitem ( key , value ) <EOL> self . _menu . addItem_ ( value . _menuitem ) <EOL> super ( Menu , self ) . __setitem__ ( key , value ) <EOL> def __delitem__ ( self , key ) : <EOL> value = self [ key ] <EOL> self . _menu . removeItem_ ( value . _menuitem ) <EOL> super ( Menu , self ) . __delitem__ ( key ) <EOL> def add ( self , menuitem ) : <EOL> self . __setitem__ ( self . _choose_key , menuitem ) <EOL> def clear ( self ) : <EOL> self . _menu . removeAllItems ( ) <EOL> super ( Menu , self ) . clear ( ) <EOL> def copy ( self ) : <EOL> raise NotImplementedError <EOL> @ classmethod <EOL> def fromkeys ( cls , * args , ** kwargs ) : <EOL> raise NotImplementedError <EOL> def update ( self , iterable , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> def parse_menu ( iterable , menu , depth ) : <EOL> if isinstance ( iterable , MenuItem ) : <EOL> menu . add ( iterable ) <EOL> return <EOL> for n , ele in enumerate ( iterable . iteritems ( ) if isinstance ( iterable , Mapping ) else iterable ) : <EOL> if not isinstance ( ele , MenuItem ) and isinstance ( ele , Mapping ) : <EOL> parse_menu ( ele , menu , depth ) <EOL> elif not isinstance ( ele , ( basestring , MenuItem ) ) and isinstance ( ele , Iterable ) : <EOL> try : <EOL> menuitem , submenu = ele <EOL> except TypeError : <EOL> raise ValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' . format ( n , depth , len ( tuple ( ele ) ) ) ) <EOL> menuitem = MenuItem ( menuitem ) <EOL> menu . add ( menuitem ) <EOL> parse_menu ( submenu , menuitem , depth + <NUM_LIT:1> ) <EOL> else : <EOL> menu . add ( ele ) <EOL> parse_menu ( iterable , self , <NUM_LIT:0> ) <EOL> parse_menu ( kwargs , self , <NUM_LIT:0> ) <EOL> def insert_after ( self , existing_key , menuitem ) : <EOL> key , menuitem = self . _process_new_menuitem ( self . _choose_key , menuitem ) <EOL> self . _insert_helper ( existing_key , key , menuitem , <NUM_LIT:1> ) <EOL> super ( Menu , self ) . insert_after ( existing_key , ( key , menuitem ) ) <EOL> def insert_before ( self , existing_key , menuitem ) : <EOL> key , menuitem = self . _process_new_menuitem ( self . _choose_key , menuitem ) <EOL> self . _insert_helper ( existing_key , key , menuitem , <NUM_LIT:0> ) <EOL> super ( Menu , self ) . insert_before ( existing_key , ( key , menuitem ) ) <EOL> def _insert_helper ( self , existing_key , key , menuitem , pos ) : <EOL> if existing_key == key : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> existing_menuitem = self [ existing_key ] <EOL> index = self . _menu . indexOfItem_ ( existing_menuitem . _menuitem ) <EOL> self . _menu . insertItem_atIndex_ ( menuitem . _menuitem , index + pos ) <EOL> def _process_new_menuitem ( self , key , value ) : <EOL> if value is None : <EOL> value = separator <EOL> if value is not separator : <EOL> value = MenuItem ( value ) <EOL> if key is self . _choose_key : <EOL> key = value . title <EOL> if key != value . title : <EOL> _log ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' . format ( repr ( key ) , repr ( value . title ) ) ) <EOL> else : <EOL> value = SeparatorMenuItem ( ) <EOL> if key is self . _choose_key : <EOL> key = '<STR_LIT>' + str ( self . _separators ) <EOL> self . _separators += <NUM_LIT:1> <EOL> return key , value <EOL> class MenuItemCallbackHolder ( NSObject ) : <EOL> _instance = None <EOL> _ns_to_py_and_callback = { } <EOL> @ classmethod <EOL> def instance ( cls ) : <EOL> if cls . _instance is None : <EOL> cls . _instance = cls . alloc ( ) . init ( ) <EOL> return cls . _instance <EOL> def callback_ ( self , nsmenuitem ) : <EOL> iteminstance , callback = self . _ns_to_py_and_callback [ nsmenuitem ] <EOL> _log ( iteminstance ) <EOL> return _call_as_function_or_method ( callback , iteminstance ) <EOL> class MenuItem ( Menu ) : <EOL> """<STR_LIT>""" <EOL> def __new__ ( cls , * args , ** kwargs ) : <EOL> if args and isinstance ( args [ <NUM_LIT:0> ] , MenuItem ) : <EOL> return args [ <NUM_LIT:0> ] <EOL> return super ( MenuItem , cls ) . __new__ ( cls , * args , ** kwargs ) <EOL> def __init__ ( self , title , callback = None , key = '<STR_LIT>' , icon = None , dimensions = None ) : <EOL> if isinstance ( title , MenuItem ) : <EOL> return <EOL> self . _holder = MenuItemCallbackHolder . instance ( ) <EOL> self . _menuitem = NSMenuItem . alloc ( ) . initWithTitle_action_keyEquivalent_ ( str ( title ) , None , '<STR_LIT>' ) <EOL> if callable ( callback ) : <EOL> self . set_callback ( callback , key ) <EOL> self . _menu = self . _icon = None <EOL> self . set_icon ( icon , dimensions ) <EOL> super ( MenuItem , self ) . __init__ ( ) <EOL> def __setitem__ ( self , key , value ) : <EOL> if self . _menu is None : <EOL> self . _menu = NSMenu . alloc ( ) . init ( ) <EOL> self . _menuitem . setSubmenu_ ( self . _menu ) <EOL> super ( MenuItem , self ) . __setitem__ ( key , value ) <EOL> def __repr__ ( self ) : <EOL> try : <EOL> callback = MenuItemCallbackHolder . _ns_to_py_and_callback [ self . _menuitem ] [ <NUM_LIT:1> ] <EOL> except KeyError : <EOL> callback = None <EOL> return '<STR_LIT>' . format ( type ( self ) . __name__ , repr ( self . title ) , map ( str , self ) , <EOL> repr ( callback ) ) <EOL> @ property <EOL> def title ( self ) : <EOL> return self . _menuitem . title ( ) <EOL> @ title . setter <EOL> def title ( self , new_title ) : <EOL> new_title = str ( new_title ) <EOL> self . _menuitem . setTitle_ ( new_title ) <EOL> @ property <EOL> def icon ( self ) : <EOL> return self . _icon <EOL> @ icon . setter <EOL> def icon ( self , icon_path ) : <EOL> self . set_icon ( icon_path ) <EOL> def set_icon ( self , icon_path , dimensions = None ) : <EOL> if icon_path is None : <EOL> return <EOL> if dimensions is not None and len ( dimensions ) != <NUM_LIT:2> : <EOL> dimensions = None <EOL> image = _nsimage_from_file ( icon_path , dimensions ) <EOL> self . _icon = image <EOL> self . _menuitem . setImage_ ( image ) <EOL> @ property <EOL> def state ( self ) : <EOL> return self . _menuitem . state ( ) <EOL> @ state . setter <EOL> def state ( self , new_state ) : <EOL> self . _menuitem . setState_ ( new_state ) <EOL> def set_callback ( self , callback , key = '<STR_LIT>' ) : <EOL> MenuItemCallbackHolder . _ns_to_py_and_callback [ self . _menuitem ] = self , callback <EOL> self . _menuitem . setAction_ ( '<STR_LIT>' ) <EOL> self . _menuitem . setTarget_ ( self . _holder ) <EOL> self . _menuitem . setKeyEquivalent_ ( key ) <EOL> class SeparatorMenuItem ( object ) : <EOL> def __init__ ( self ) : <EOL> self . _menuitem = NSMenuItem . separatorItem ( ) <EOL> class Timer ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , callback , interval ) : <EOL> self . set_callback ( callback ) <EOL> self . _interval = interval <EOL> self . _status = False <EOL> def __call__ ( self ) : <EOL> return self . _nstimer <EOL> def __repr__ ( self ) : <EOL> return ( '<STR_LIT>' <EOL> '<STR_LIT>' ) . format ( type ( self ) . __name__ , repr ( getattr ( self , '<STR_LIT>' ) . __name__ ) , <EOL> self . _interval , '<STR_LIT>' if self . _status else '<STR_LIT>' ) <EOL> @ property <EOL> def interval ( self ) : <EOL> return self . _interval <EOL> @ interval . setter <EOL> def interval ( self , new_interval ) : <EOL> if self . _status : <EOL> if abs ( self . _nsdate . timeIntervalSinceNow ( ) ) >= self . _nstimer . timeInterval ( ) : <EOL> self . stop ( ) <EOL> self . _interval = new_interval <EOL> self . start ( ) <EOL> else : <EOL> self . _interval = new_interval <EOL> @ property <EOL> def callback ( self ) : <EOL> return getattr ( self , '<STR_LIT>' ) <EOL> def is_alive ( self ) : <EOL> return self . _status <EOL> def start ( self ) : <EOL> if not self . _status : <EOL> self . _nsdate = NSDate . date ( ) <EOL> self . _nstimer = NSTimer . alloc ( ) . initWithFireDate_interval_target_selector_userInfo_repeats_ ( <EOL> self . _nsdate , self . _interval , self , '<STR_LIT>' , None , True ) <EOL> NSRunLoop . currentRunLoop ( ) . addTimer_forMode_ ( self . _nstimer , NSDefaultRunLoopMode ) <EOL> _TIMERS . add ( self ) <EOL> self . _status = True <EOL> def stop ( self ) : <EOL> if self . _status : <EOL> self . _nstimer . invalidate ( ) <EOL> del self . _nstimer <EOL> del self . _nsdate <EOL> self . _status = False <EOL> def set_callback ( self , callback ) : <EOL> setattr ( self , '<STR_LIT>' , callback ) <EOL> def callback_ ( self , _ ) : <EOL> _log ( self ) <EOL> return _call_as_function_or_method ( getattr ( self , '<STR_LIT>' ) , self ) <EOL> class Window ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , message , title = '<STR_LIT>' , default_text = '<STR_LIT>' , ok = None , cancel = False , dimensions = ( <NUM_LIT> , <NUM_LIT> ) ) : <EOL> message = str ( message ) <EOL> title = str ( title ) <EOL> self . _default_text = default_text <EOL> self . _cancel = bool ( cancel ) <EOL> self . _icon = None <EOL> self . _alert = NSAlert . alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_ ( <EOL> title , ok , '<STR_LIT>' if cancel else None , None , message ) <EOL> self . _alert . setAlertStyle_ ( <NUM_LIT:0> ) <EOL> self . _textfield = NSTextField . alloc ( ) . initWithFrame_ ( NSMakeRect ( <NUM_LIT:0> , <NUM_LIT:0> , * dimensions ) ) <EOL> self . _textfield . setSelectable_ ( True ) <EOL> if default_text : <EOL> self . _textfield . setStringValue_ ( default_text ) <EOL> self . _alert . setAccessoryView_ ( self . _textfield ) <EOL> @ property <EOL> def title ( self ) : <EOL> return self . _alert . messageText ( ) <EOL> @ title . setter <EOL> def title ( self , new_title ) : <EOL> new_title = str ( new_title ) <EOL> self . _alert . setMessageText_ ( new_title ) <EOL> @ property <EOL> def message ( self ) : <EOL> return self . _alert . informativeText ( ) <EOL> @ message . setter <EOL> def message ( self , new_message ) : <EOL> new_message = str ( new_message ) <EOL> self . _alert . setInformativeText_ ( new_message ) <EOL> @ property <EOL> def default_text ( self ) : <EOL> return self . _default_text <EOL> @ default_text . setter <EOL> def default_text ( self , new_text ) : <EOL> new_text = str ( new_text ) <EOL> self . _default_text = new_text <EOL> self . _textfield . setStringValue_ ( new_text ) <EOL> @ property <EOL> def icon ( self ) : <EOL> return self . _icon <EOL> @ icon . setter <EOL> def icon ( self , icon_path ) : <EOL> new_icon = _nsimage_from_file ( icon_path ) <EOL> self . _icon = icon_path <EOL> self . _alert . setIcon_ ( new_icon ) <EOL> def add_button ( self , name ) : <EOL> name = str ( name ) <EOL> self . _alert . addButtonWithTitle_ ( name ) <EOL> def add_buttons ( self , iterable = None , * args ) : <EOL> if iterable is None : <EOL> return <EOL> if isinstance ( iterable , basestring ) : <EOL> self . add_button ( iterable ) <EOL> else : <EOL> for ele in iterable : <EOL> self . add_button ( ele ) <EOL> for arg in args : <EOL> self . add_button ( arg ) <EOL> def run ( self ) : <EOL> _log ( self ) <EOL> clicked = self . _alert . runModal ( ) % <NUM_LIT> <EOL> if clicked > <NUM_LIT:2> and self . _cancel : <EOL> clicked -= <NUM_LIT:1> <EOL> self . _textfield . validateEditing ( ) <EOL> text = self . _textfield . stringValue ( ) <EOL> self . default_text = self . _default_text <EOL> return Response ( clicked , text ) <EOL> class Response ( object ) : <EOL> def __init__ ( self , clicked , text ) : <EOL> self . _clicked = clicked <EOL> self . _text = text <EOL> def __repr__ ( self ) : <EOL> shortened_text = self . _text if len ( self . _text ) < <NUM_LIT> else self . _text [ : <NUM_LIT> ] + '<STR_LIT>' <EOL> return '<STR_LIT>' . format ( type ( self ) . __name__ , self . _clicked , repr ( shortened_text ) ) <EOL> @ property <EOL> def clicked ( self ) : <EOL> return self . _clicked <EOL> @ property <EOL> def text ( self ) : <EOL> return self . _text <EOL> class NSApp ( NSObject ) : <EOL> """<STR_LIT>""" <EOL> def userNotificationCenter_didActivateNotification_ ( self , notification_center , notification ) : <EOL> notification_center . removeDeliveredNotification_ ( notification ) <EOL> data = dict ( notification . userInfo ( ) ) <EOL> try : <EOL> _call_as_function_or_method ( getattr ( notifications , '<STR_LIT>' ) , data ) <EOL> except AttributeError : <EOL> _log ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> def initializeStatusBar ( self ) : <EOL> self . nsstatusitem = NSStatusBar . systemStatusBar ( ) . statusItemWithLength_ ( - <NUM_LIT:1> ) <EOL> self . nsstatusitem . setHighlightMode_ ( True ) <EOL> if self . _app [ '<STR_LIT>' ] is not None : <EOL> self . setStatusBarIcon ( ) <EOL> _log ( '<STR_LIT>' ) <EOL> if self . _app [ '<STR_LIT>' ] is not None : <EOL> self . setStatusBarTitle ( ) <EOL> else : <EOL> self . setStatusBarTitle ( ) <EOL> mainmenu = self . _app [ '<STR_LIT>' ] <EOL> mainmenu . add ( '<STR_LIT>' ) <EOL> mainmenu [ '<STR_LIT>' ] . _menuitem . setAction_ ( '<STR_LIT>' ) <EOL> self . nsstatusitem . setMenu_ ( mainmenu . _menu ) <EOL> def setStatusBarTitle ( self ) : <EOL> self . nsstatusitem . setTitle_ ( self . _app [ '<STR_LIT>' ] if self . _app [ '<STR_LIT>' ] is not None else self . _app [ '<STR_LIT>' ] ) <EOL> def setStatusBarIcon ( self ) : <EOL> self . nsstatusitem . setImage_ ( _nsimage_from_file ( self . _app [ '<STR_LIT>' ] ) ) <EOL> class App ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name , title = None , icon = None , menu = None ) : <EOL> self . _name = str ( name ) <EOL> self . _icon = self . _title = None <EOL> self . icon = icon <EOL> self . title = title <EOL> self . _menu = Menu ( ) <EOL> if menu is not None : <EOL> self . menu = menu <EOL> self . _application_support = application_support ( self . _name ) <EOL> @ property <EOL> def name ( self ) : <EOL> return self . _name <EOL> @ property <EOL> def title ( self ) : <EOL> return self . _title <EOL> @ title . setter <EOL> def title ( self , title ) : <EOL> if title is None : <EOL> return <EOL> self . _title = str ( title ) <EOL> try : <EOL> self . _nsapp . setStatusBarTitle ( ) <EOL> except AttributeError : <EOL> pass <EOL> @ property <EOL> def icon ( self ) : <EOL> return self . _icon <EOL> @ icon . setter <EOL> def icon ( self , icon_path ) : <EOL> if icon_path is None : <EOL> return <EOL> self . _icon = icon_path <EOL> try : <EOL> self . _nsapp . setStatusBarIcon ( ) <EOL> except AttributeError : <EOL> pass <EOL> @ property <EOL> def menu ( self ) : <EOL> return self . _menu <EOL> @ menu . setter <EOL> def menu ( self , iterable ) : <EOL> self . _menu . update ( iterable ) <EOL> def open ( self , * args ) : <EOL> return open ( os . path . join ( self . _application_support , args [ <NUM_LIT:0> ] ) , * args [ <NUM_LIT:1> : ] ) <EOL> def run ( self ) : <EOL> """<STR_LIT>""" <EOL> nsapplication = NSApplication . sharedApplication ( ) <EOL> nsapplication . activateIgnoringOtherApps_ ( True ) <EOL> self . _nsapp = NSApp . alloc ( ) . init ( ) <EOL> self . _nsapp . _app = self . __dict__ <EOL> self . _nsapp . initializeStatusBar ( ) <EOL> nsapplication . setDelegate_ ( self . _nsapp ) <EOL> setattr ( App , '<STR_LIT>' , self ) <EOL> t = b = None <EOL> for t in getattr ( timer , '<STR_LIT>' , [ ] ) : <EOL> t . start ( ) <EOL> for b in getattr ( clicked , '<STR_LIT>' , [ ] ) : <EOL> b ( self ) <EOL> del t , b <EOL> AppHelper . runEventLoop ( ) </s>
