teacup 1.3.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +1172 -319
- data/Rakefile +8 -1
- data/app/app_delegate.rb +1 -1
- data/app/controllers/appearance_controller.rb +13 -0
- data/app/controllers/landscape_only_controller.rb +1 -1
- data/app/controllers/{first_controller.rb → main_controller.rb} +4 -3
- data/app/controllers/motion_layout_controller.rb +22 -0
- data/app/styles/appearance.rb +24 -0
- data/app/styles/main_styles.rb +8 -6
- data/app/views/custom_view.rb +1 -0
- data/lib/teacup/calculations.rb +2 -2
- data/lib/teacup/{z_core_extensions → core_extensions}/ca_layer.rb +0 -0
- data/lib/teacup/core_extensions/view_getters.rb +61 -0
- data/lib/teacup/handler.rb +14 -14
- data/lib/teacup/layout.rb +94 -17
- data/lib/teacup/stylesheet.rb +61 -26
- data/lib/teacup/stylesheet_extensions/transform.rb +88 -0
- data/lib/teacup/teacup_controller.rb +122 -0
- data/lib/teacup/teacup_util.rb +12 -7
- data/lib/teacup/teacup_view.rb +329 -0
- data/lib/teacup/version.rb +1 -1
- data/lib/teacup-ios/appearance.rb +96 -0
- data/lib/teacup-ios/core_extensions/teacup_handlers.rb +183 -0
- data/lib/teacup-ios/core_extensions/ui_view.rb +30 -0
- data/lib/teacup-ios/core_extensions/ui_view_controller.rb +110 -0
- data/lib/{dummy.rb → teacup-ios/dummy.rb} +2 -6
- data/lib/teacup-ios/handler.rb +23 -0
- data/lib/{teacup → teacup-ios}/style.rb +9 -10
- data/lib/teacup-ios/stylesheet_extensions/autoresize.rb +169 -0
- data/lib/{teacup/stylesheet_extensions/geometry.rb → teacup-ios/stylesheet_extensions/device.rb} +0 -0
- data/lib/teacup-osx/core_extensions/ns_view.rb +39 -0
- data/lib/teacup-osx/core_extensions/ns_view_controller.rb +21 -0
- data/lib/teacup-osx/core_extensions/ns_window.rb +39 -0
- data/lib/teacup-osx/core_extensions/ns_window_controller.rb +29 -0
- data/lib/{teacup/z_core_extensions/z_handlers.rb → teacup-osx/core_extensions/teacup_handlers.rb} +30 -47
- data/lib/teacup-osx/dummy.rb +80 -0
- data/lib/teacup-osx/handler.rb +16 -0
- data/lib/teacup-osx/style.rb +83 -0
- data/lib/teacup-osx/style_extensions/autoresize.rb +169 -0
- data/lib/teacup.rb +12 -11
- data/samples/Tweets/Gemfile +4 -0
- data/samples/Tweets/Gemfile.lock +16 -0
- data/samples/Tweets/README +7 -0
- data/samples/Tweets/Rakefile +9 -0
- data/samples/Tweets/app/app_delegate.rb +18 -0
- data/samples/Tweets/app/data_parser.rb +10 -0
- data/samples/Tweets/app/json_parser.rb +12 -0
- data/samples/Tweets/app/main_window.rb +99 -0
- data/samples/Tweets/app/menu.rb +108 -0
- data/samples/Tweets/app/stylesheet.rb +21 -0
- data/samples/Tweets/app/tweet.rb +11 -0
- data/samples/Tweets/resources/Credits.rtf +29 -0
- data/samples/Tweets/spec/main_spec.rb +9 -0
- data/samples/teacup-osx/.gitignore +1 -0
- data/samples/teacup-osx/Gemfile +4 -0
- data/samples/teacup-osx/Gemfile.lock +16 -0
- data/samples/teacup-osx/Rakefile +9 -0
- data/samples/teacup-osx/app/app_delegate.rb +23 -0
- data/samples/teacup-osx/app/controller.rb +11 -0
- data/samples/teacup-osx/app/menu.rb +108 -0
- data/samples/teacup-osx/app/window.rb +12 -0
- data/samples/teacup-osx/resources/Credits.rtf +29 -0
- data/samples/teacup-osx/resources/teacup.png +0 -0
- data/samples/teacup-osx/spec/main_spec.rb +9 -0
- data/spec/ios/appearance_spec.rb +18 -0
- data/spec/{calculations_spec.rb → ios/calculations_spec.rb} +0 -0
- data/spec/{constraints_spec.rb → ios/constraints_spec.rb} +0 -0
- data/spec/{custom_class_spec.rb → ios/custom_class_spec.rb} +0 -0
- data/spec/{gradient_spec.rb → ios/gradient_spec.rb} +1 -1
- data/spec/ios/layout_module_spec.rb +54 -0
- data/spec/ios/layout_spec.rb +50 -0
- data/spec/{main_spec.rb → ios/main_spec.rb} +52 -13
- data/spec/ios/motion_layout_spec.rb +44 -0
- data/spec/{present_modal_spec.rb → ios/present_modal_spec.rb} +0 -0
- data/spec/{style_spec.rb → ios/style_spec.rb} +1 -1
- data/spec/ios/stylesheet_extensions/autoresize_spec.rb +50 -0
- data/spec/{stylesheet_spec.rb → ios/stylesheet_spec.rb} +12 -0
- data/spec/{ui_view_getters_spec.rb → ios/ui_view_getters_spec.rb} +0 -0
- data/spec/{uiswitch_spec.rb → ios/uiswitch_spec.rb} +0 -0
- data/spec/{view_spec.rb → ios/view_spec.rb} +23 -2
- metadata +85 -35
- data/lib/teacup/stylesheet_extensions/autoresize.rb +0 -39
- data/lib/teacup/stylesheet_extensions/rotation.rb +0 -37
- data/lib/teacup/z_core_extensions/ui_view.rb +0 -262
- data/lib/teacup/z_core_extensions/ui_view_controller.rb +0 -263
- data/lib/teacup/z_core_extensions/ui_view_getters.rb +0 -58
@@ -0,0 +1,99 @@
|
|
1
|
+
class MainController < TeacupWindowController
|
2
|
+
stylesheet :main_window
|
3
|
+
|
4
|
+
layout do
|
5
|
+
@text_search = subview(NSTextField, :text_search,
|
6
|
+
stringValue: 'xcode crash'
|
7
|
+
)
|
8
|
+
|
9
|
+
subview(NSButton, :search_button,
|
10
|
+
action: 'search:',
|
11
|
+
target: self,
|
12
|
+
)
|
13
|
+
|
14
|
+
scroll_view = subview(NSScrollView, :scroll_view)
|
15
|
+
|
16
|
+
@table_view = subview(NSTableView, :table_view,
|
17
|
+
delegate: self,
|
18
|
+
dataSource: self,
|
19
|
+
)
|
20
|
+
|
21
|
+
column_avatar = NSTableColumn.alloc.initWithIdentifier("avatar")
|
22
|
+
column_avatar.editable = false
|
23
|
+
column_avatar.headerCell.setTitle("Avator")
|
24
|
+
column_avatar.setWidth(40)
|
25
|
+
column_avatar.setDataCell(NSImageCell.alloc.init)
|
26
|
+
@table_view.addTableColumn(column_avatar)
|
27
|
+
|
28
|
+
column_name = NSTableColumn.alloc.initWithIdentifier("name")
|
29
|
+
column_name.editable = false
|
30
|
+
column_name.headerCell.setTitle("Name")
|
31
|
+
column_name.setWidth(150)
|
32
|
+
@table_view.addTableColumn(column_name)
|
33
|
+
|
34
|
+
column_tweet = NSTableColumn.alloc.initWithIdentifier("tweet")
|
35
|
+
column_tweet.editable = false
|
36
|
+
column_tweet.headerCell.setTitle("Tweet")
|
37
|
+
column_tweet.setWidth(290)
|
38
|
+
@table_view.addTableColumn(column_tweet)
|
39
|
+
|
40
|
+
scroll_view.setDocumentView(@table_view)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def search(sender)
|
45
|
+
text = @text_search.stringValue
|
46
|
+
if text.length > 0
|
47
|
+
query = text.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
|
48
|
+
url = "http://search.twitter.com/search.json?q=#{query}"
|
49
|
+
|
50
|
+
Dispatch::Queue.concurrent.async do
|
51
|
+
json = nil
|
52
|
+
begin
|
53
|
+
json = JSONParser.parse_from_url(url)
|
54
|
+
rescue RuntimeError => e
|
55
|
+
presentError e.message
|
56
|
+
end
|
57
|
+
|
58
|
+
@search_result = []
|
59
|
+
json['results'].each do |dict|
|
60
|
+
tweet = Tweet.new(dict)
|
61
|
+
@search_result << tweet
|
62
|
+
|
63
|
+
Dispatch::Queue.concurrent.async do
|
64
|
+
profile_image_data = NSData.alloc.initWithContentsOfURL(NSURL.URLWithString(tweet.profile_image_url))
|
65
|
+
if profile_image_data
|
66
|
+
tweet.profile_image = NSImage.alloc.initWithData(profile_image_data)
|
67
|
+
Dispatch::Queue.main.sync do
|
68
|
+
@table_view.reloadData
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Dispatch::Queue.main.sync { @table_view.reloadData }
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def numberOfRowsInTableView(aTableView)
|
81
|
+
return 0 if @search_result.nil?
|
82
|
+
return @search_result.size
|
83
|
+
end
|
84
|
+
|
85
|
+
def tableView(aTableView,
|
86
|
+
objectValueForTableColumn: aTableColumn,
|
87
|
+
row: rowIndex)
|
88
|
+
case aTableColumn.identifier
|
89
|
+
when "avatar"
|
90
|
+
return @search_result[rowIndex].profile_image
|
91
|
+
when "name"
|
92
|
+
return @search_result[rowIndex].author
|
93
|
+
when "tweet"
|
94
|
+
return @search_result[rowIndex].message
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class AppDelegate
|
2
|
+
def buildMenu
|
3
|
+
@mainMenu = NSMenu.new
|
4
|
+
|
5
|
+
appName = NSBundle.mainBundle.infoDictionary['CFBundleName']
|
6
|
+
addMenu(appName) do
|
7
|
+
addItemWithTitle("About #{appName}", action: 'orderFrontStandardAboutPanel:', keyEquivalent: '')
|
8
|
+
addItem(NSMenuItem.separatorItem)
|
9
|
+
addItemWithTitle('Preferences', action: 'openPreferences:', keyEquivalent: ',')
|
10
|
+
addItem(NSMenuItem.separatorItem)
|
11
|
+
servicesItem = addItemWithTitle('Services', action: nil, keyEquivalent: '')
|
12
|
+
NSApp.servicesMenu = servicesItem.submenu = NSMenu.new
|
13
|
+
addItem(NSMenuItem.separatorItem)
|
14
|
+
addItemWithTitle("Hide #{appName}", action: 'hide:', keyEquivalent: 'h')
|
15
|
+
item = addItemWithTitle('Hide Others', action: 'hideOtherApplications:', keyEquivalent: 'H')
|
16
|
+
item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask
|
17
|
+
addItemWithTitle('Show All', action: 'unhideAllApplications:', keyEquivalent: '')
|
18
|
+
addItem(NSMenuItem.separatorItem)
|
19
|
+
addItemWithTitle("Quit #{appName}", action: 'terminate:', keyEquivalent: 'q')
|
20
|
+
end
|
21
|
+
|
22
|
+
addMenu('File') do
|
23
|
+
addItemWithTitle('New', action: 'newDocument:', keyEquivalent: 'n')
|
24
|
+
addItemWithTitle('Open…', action: 'openDocument:', keyEquivalent: 'o')
|
25
|
+
addItem(NSMenuItem.separatorItem)
|
26
|
+
addItemWithTitle('Close', action: 'performClose:', keyEquivalent: 'w')
|
27
|
+
addItemWithTitle('Save…', action: 'saveDocument:', keyEquivalent: 's')
|
28
|
+
addItemWithTitle('Revert to Saved', action: 'revertDocumentToSaved:', keyEquivalent: '')
|
29
|
+
addItem(NSMenuItem.separatorItem)
|
30
|
+
addItemWithTitle('Page Setup…', action: 'runPageLayout:', keyEquivalent: 'P')
|
31
|
+
addItemWithTitle('Print…', action: 'printDocument:', keyEquivalent: 'p')
|
32
|
+
end
|
33
|
+
|
34
|
+
addMenu('Edit') do
|
35
|
+
addItemWithTitle('Undo', action: 'undo:', keyEquivalent: 'z')
|
36
|
+
addItemWithTitle('Redo', action: 'redo:', keyEquivalent: 'Z')
|
37
|
+
addItem(NSMenuItem.separatorItem)
|
38
|
+
addItemWithTitle('Cut', action: 'cut:', keyEquivalent: 'x')
|
39
|
+
addItemWithTitle('Copy', action: 'copy:', keyEquivalent: 'c')
|
40
|
+
addItemWithTitle('Paste', action: 'paste:', keyEquivalent: 'v')
|
41
|
+
item = addItemWithTitle('Paste and Match Style', action: 'pasteAsPlainText:', keyEquivalent: 'V')
|
42
|
+
item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask
|
43
|
+
addItemWithTitle('Delete', action: 'delete:', keyEquivalent: '')
|
44
|
+
addItemWithTitle('Select All', action: 'selectAll:', keyEquivalent: 'a')
|
45
|
+
end
|
46
|
+
|
47
|
+
fontMenu = createMenu('Font') do
|
48
|
+
addItemWithTitle('Show Fonts', action: 'orderFrontFontPanel:', keyEquivalent: 't')
|
49
|
+
addItemWithTitle('Bold', action: 'addFontTrait:', keyEquivalent: 'b')
|
50
|
+
addItemWithTitle('Italic', action: 'addFontTrait:', keyEquivalent: 'b')
|
51
|
+
addItemWithTitle('Underline', action: 'underline:', keyEquivalent: 'u')
|
52
|
+
addItem(NSMenuItem.separatorItem)
|
53
|
+
addItemWithTitle('Bigger', action: 'modifyFont:', keyEquivalent: '+')
|
54
|
+
addItemWithTitle('Smaller', action: 'modifyFont:', keyEquivalent: '-')
|
55
|
+
end
|
56
|
+
|
57
|
+
textMenu = createMenu('Text') do
|
58
|
+
addItemWithTitle('Align Left', action: 'alignLeft:', keyEquivalent: '{')
|
59
|
+
addItemWithTitle('Center', action: 'alignCenter:', keyEquivalent: '|')
|
60
|
+
addItemWithTitle('Justify', action: 'alignJustified:', keyEquivalent: '')
|
61
|
+
addItemWithTitle('Align Right', action: 'alignRight:', keyEquivalent: '}')
|
62
|
+
addItem(NSMenuItem.separatorItem)
|
63
|
+
addItemWithTitle('Show Ruler', action: 'toggleRuler:', keyEquivalent: '')
|
64
|
+
addItemWithTitle('Copy Ruler', action: 'copyRuler:', keyEquivalent: 'c')
|
65
|
+
addItemWithTitle('Paste Ruler', action: 'pasteRuler:', keyEquivalent: 'v')
|
66
|
+
end
|
67
|
+
|
68
|
+
addMenu('Format') do
|
69
|
+
addItem fontMenu
|
70
|
+
addItem textMenu
|
71
|
+
end
|
72
|
+
|
73
|
+
addMenu('View') do
|
74
|
+
item = addItemWithTitle('Show Toolbar', action: 'toggleToolbarShown:', keyEquivalent: 't')
|
75
|
+
item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask
|
76
|
+
addItemWithTitle('Customize Toolbar…', action: 'runToolbarCustomizationPalette:', keyEquivalent: '')
|
77
|
+
end
|
78
|
+
|
79
|
+
NSApp.windowsMenu = addMenu('Window') do
|
80
|
+
addItemWithTitle('Minimize', action: 'performMiniaturize:', keyEquivalent: 'm')
|
81
|
+
addItemWithTitle('Zoom', action: 'performZoom:', keyEquivalent: '')
|
82
|
+
addItem(NSMenuItem.separatorItem)
|
83
|
+
addItemWithTitle('Bring All To Front', action: 'arrangeInFront:', keyEquivalent: '')
|
84
|
+
end.menu
|
85
|
+
|
86
|
+
NSApp.helpMenu = addMenu('Help') do
|
87
|
+
addItemWithTitle("#{appName} Help", action: 'showHelp:', keyEquivalent: '?')
|
88
|
+
end.menu
|
89
|
+
|
90
|
+
NSApp.mainMenu = @mainMenu
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def addMenu(title, &b)
|
96
|
+
item = createMenu(title, &b)
|
97
|
+
@mainMenu.addItem item
|
98
|
+
item
|
99
|
+
end
|
100
|
+
|
101
|
+
def createMenu(title, &b)
|
102
|
+
menu = NSMenu.alloc.initWithTitle(title)
|
103
|
+
menu.instance_eval(&b) if b
|
104
|
+
item = NSMenuItem.alloc.initWithTitle(title, action: nil, keyEquivalent: '')
|
105
|
+
item.submenu = menu
|
106
|
+
item
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Teacup::Stylesheet.new :main_window do
|
2
|
+
|
3
|
+
style :text_search,
|
4
|
+
frame: NSMakeRect(20, 318, 341, 22),
|
5
|
+
autoresizingMask: autoresize.fill_top
|
6
|
+
|
7
|
+
style :search_button,
|
8
|
+
frame: NSMakeRect(384, 310, 82, 32),
|
9
|
+
title: "Search",
|
10
|
+
bezelStyle: NSRoundedBezelStyle,
|
11
|
+
autoresizingMask: autoresize.fixed_top_right
|
12
|
+
|
13
|
+
style :scroll_view,
|
14
|
+
frame: NSMakeRect(0, 0, 480, 300),
|
15
|
+
autoresizingMask: autoresize.fill,
|
16
|
+
hasVerticalScroller: true
|
17
|
+
|
18
|
+
style :table_view,
|
19
|
+
autoresizingMask: autoresize.fill
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Tweet
|
2
|
+
attr_reader :author, :message, :profile_image_url
|
3
|
+
attr_accessor :profile_image
|
4
|
+
|
5
|
+
def initialize(dict)
|
6
|
+
@author = dict['from_user_name']
|
7
|
+
@message = dict['text']
|
8
|
+
@profile_image_url = dict['profile_image_url']
|
9
|
+
@profile_image = nil
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
|
2
|
+
{\colortbl;\red255\green255\blue255;}
|
3
|
+
\paperw9840\paperh8400
|
4
|
+
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
|
5
|
+
|
6
|
+
\f0\b\fs24 \cf0 Engineering:
|
7
|
+
\b0 \
|
8
|
+
Some people\
|
9
|
+
\
|
10
|
+
|
11
|
+
\b Human Interface Design:
|
12
|
+
\b0 \
|
13
|
+
Some other people\
|
14
|
+
\
|
15
|
+
|
16
|
+
\b Testing:
|
17
|
+
\b0 \
|
18
|
+
Hopefully not nobody\
|
19
|
+
\
|
20
|
+
|
21
|
+
\b Documentation:
|
22
|
+
\b0 \
|
23
|
+
Whoever\
|
24
|
+
\
|
25
|
+
|
26
|
+
\b With special thanks to:
|
27
|
+
\b0 \
|
28
|
+
Mom\
|
29
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
.dat*
|
@@ -0,0 +1,23 @@
|
|
1
|
+
include SugarCube::Adjust
|
2
|
+
|
3
|
+
|
4
|
+
class AppDelegate
|
5
|
+
def applicationDidFinishLaunching(notification)
|
6
|
+
buildMenu
|
7
|
+
buildWindow
|
8
|
+
end
|
9
|
+
|
10
|
+
def buildWindow
|
11
|
+
@controller = MainWindowController.new
|
12
|
+
@mainWindow = @controller.window
|
13
|
+
@table_view_controller = MainTableController.new
|
14
|
+
|
15
|
+
# @mainWindow = NSWindow.alloc.initWithContentRect([[240, 180], [480, 360]],
|
16
|
+
# styleMask: NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
|
17
|
+
# backing: NSBackingStoreBuffered,
|
18
|
+
# defer: false)
|
19
|
+
@mainWindow.title = NSBundle.mainBundle.infoDictionary['CFBundleName']
|
20
|
+
@mainWindow.orderFrontRegardless
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class AppDelegate
|
2
|
+
def buildMenu
|
3
|
+
@mainMenu = NSMenu.new
|
4
|
+
|
5
|
+
appName = NSBundle.mainBundle.infoDictionary['CFBundleName']
|
6
|
+
addMenu(appName) do
|
7
|
+
addItemWithTitle("About #{appName}", action: 'orderFrontStandardAboutPanel:', keyEquivalent: '')
|
8
|
+
addItem(NSMenuItem.separatorItem)
|
9
|
+
addItemWithTitle('Preferences', action: 'openPreferences:', keyEquivalent: ',')
|
10
|
+
addItem(NSMenuItem.separatorItem)
|
11
|
+
servicesItem = addItemWithTitle('Services', action: nil, keyEquivalent: '')
|
12
|
+
NSApp.servicesMenu = servicesItem.submenu = NSMenu.new
|
13
|
+
addItem(NSMenuItem.separatorItem)
|
14
|
+
addItemWithTitle("Hide #{appName}", action: 'hide:', keyEquivalent: 'h')
|
15
|
+
item = addItemWithTitle('Hide Others', action: 'hideOtherApplications:', keyEquivalent: 'H')
|
16
|
+
item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask
|
17
|
+
addItemWithTitle('Show All', action: 'unhideAllApplications:', keyEquivalent: '')
|
18
|
+
addItem(NSMenuItem.separatorItem)
|
19
|
+
addItemWithTitle("Quit #{appName}", action: 'terminate:', keyEquivalent: 'q')
|
20
|
+
end
|
21
|
+
|
22
|
+
addMenu('File') do
|
23
|
+
addItemWithTitle('New', action: 'newDocument:', keyEquivalent: 'n')
|
24
|
+
addItemWithTitle('Open…', action: 'openDocument:', keyEquivalent: 'o')
|
25
|
+
addItem(NSMenuItem.separatorItem)
|
26
|
+
addItemWithTitle('Close', action: 'performClose:', keyEquivalent: 'w')
|
27
|
+
addItemWithTitle('Save…', action: 'saveDocument:', keyEquivalent: 's')
|
28
|
+
addItemWithTitle('Revert to Saved', action: 'revertDocumentToSaved:', keyEquivalent: '')
|
29
|
+
addItem(NSMenuItem.separatorItem)
|
30
|
+
addItemWithTitle('Page Setup…', action: 'runPageLayout:', keyEquivalent: 'P')
|
31
|
+
addItemWithTitle('Print…', action: 'printDocument:', keyEquivalent: 'p')
|
32
|
+
end
|
33
|
+
|
34
|
+
addMenu('Edit') do
|
35
|
+
addItemWithTitle('Undo', action: 'undo:', keyEquivalent: 'z')
|
36
|
+
addItemWithTitle('Redo', action: 'redo:', keyEquivalent: 'Z')
|
37
|
+
addItem(NSMenuItem.separatorItem)
|
38
|
+
addItemWithTitle('Cut', action: 'cut:', keyEquivalent: 'x')
|
39
|
+
addItemWithTitle('Copy', action: 'copy:', keyEquivalent: 'c')
|
40
|
+
addItemWithTitle('Paste', action: 'paste:', keyEquivalent: 'v')
|
41
|
+
item = addItemWithTitle('Paste and Match Style', action: 'pasteAsPlainText:', keyEquivalent: 'V')
|
42
|
+
item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask
|
43
|
+
addItemWithTitle('Delete', action: 'delete:', keyEquivalent: '')
|
44
|
+
addItemWithTitle('Select All', action: 'selectAll:', keyEquivalent: 'a')
|
45
|
+
end
|
46
|
+
|
47
|
+
fontMenu = createMenu('Font') do
|
48
|
+
addItemWithTitle('Show Fonts', action: 'orderFrontFontPanel:', keyEquivalent: 't')
|
49
|
+
addItemWithTitle('Bold', action: 'addFontTrait:', keyEquivalent: 'b')
|
50
|
+
addItemWithTitle('Italic', action: 'addFontTrait:', keyEquivalent: 'b')
|
51
|
+
addItemWithTitle('Underline', action: 'underline:', keyEquivalent: 'u')
|
52
|
+
addItem(NSMenuItem.separatorItem)
|
53
|
+
addItemWithTitle('Bigger', action: 'modifyFont:', keyEquivalent: '+')
|
54
|
+
addItemWithTitle('Smaller', action: 'modifyFont:', keyEquivalent: '-')
|
55
|
+
end
|
56
|
+
|
57
|
+
textMenu = createMenu('Text') do
|
58
|
+
addItemWithTitle('Align Left', action: 'alignLeft:', keyEquivalent: '{')
|
59
|
+
addItemWithTitle('Center', action: 'alignCenter:', keyEquivalent: '|')
|
60
|
+
addItemWithTitle('Justify', action: 'alignJustified:', keyEquivalent: '')
|
61
|
+
addItemWithTitle('Align Right', action: 'alignRight:', keyEquivalent: '}')
|
62
|
+
addItem(NSMenuItem.separatorItem)
|
63
|
+
addItemWithTitle('Show Ruler', action: 'toggleRuler:', keyEquivalent: '')
|
64
|
+
addItemWithTitle('Copy Ruler', action: 'copyRuler:', keyEquivalent: 'c')
|
65
|
+
addItemWithTitle('Paste Ruler', action: 'pasteRuler:', keyEquivalent: 'v')
|
66
|
+
end
|
67
|
+
|
68
|
+
addMenu('Format') do
|
69
|
+
addItem fontMenu
|
70
|
+
addItem textMenu
|
71
|
+
end
|
72
|
+
|
73
|
+
addMenu('View') do
|
74
|
+
item = addItemWithTitle('Show Toolbar', action: 'toggleToolbarShown:', keyEquivalent: 't')
|
75
|
+
item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask
|
76
|
+
addItemWithTitle('Customize Toolbar…', action: 'runToolbarCustomizationPalette:', keyEquivalent: '')
|
77
|
+
end
|
78
|
+
|
79
|
+
NSApp.windowsMenu = addMenu('Window') do
|
80
|
+
addItemWithTitle('Minimize', action: 'performMiniaturize:', keyEquivalent: 'm')
|
81
|
+
addItemWithTitle('Zoom', action: 'performZoom:', keyEquivalent: '')
|
82
|
+
addItem(NSMenuItem.separatorItem)
|
83
|
+
addItemWithTitle('Bring All To Front', action: 'arrangeInFront:', keyEquivalent: '')
|
84
|
+
end.menu
|
85
|
+
|
86
|
+
NSApp.helpMenu = addMenu('Help') do
|
87
|
+
addItemWithTitle("#{appName} Help", action: 'showHelp:', keyEquivalent: '?')
|
88
|
+
end.menu
|
89
|
+
|
90
|
+
NSApp.mainMenu = @mainMenu
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def addMenu(title, &b)
|
96
|
+
item = createMenu(title, &b)
|
97
|
+
@mainMenu.addItem item
|
98
|
+
item
|
99
|
+
end
|
100
|
+
|
101
|
+
def createMenu(title, &b)
|
102
|
+
menu = NSMenu.alloc.initWithTitle(title)
|
103
|
+
menu.instance_eval(&b) if b
|
104
|
+
item = NSMenuItem.alloc.initWithTitle(title, action: nil, keyEquivalent: '')
|
105
|
+
item.submenu = menu
|
106
|
+
item
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class MainWindowController < TeacupWindowController
|
2
|
+
|
3
|
+
layout do |view|
|
4
|
+
@table_view_controller = MainTableController.new
|
5
|
+
|
6
|
+
subview(@table_view_controller.view,
|
7
|
+
frame: [[10, 10], [460, 340]],
|
8
|
+
autoresizingMask: NSViewWidthSizable | NSViewHeightSizable,
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
|
2
|
+
{\colortbl;\red255\green255\blue255;}
|
3
|
+
\paperw9840\paperh8400
|
4
|
+
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
|
5
|
+
|
6
|
+
\f0\b\fs24 \cf0 Engineering:
|
7
|
+
\b0 \
|
8
|
+
Some people\
|
9
|
+
\
|
10
|
+
|
11
|
+
\b Human Interface Design:
|
12
|
+
\b0 \
|
13
|
+
Some other people\
|
14
|
+
\
|
15
|
+
|
16
|
+
\b Testing:
|
17
|
+
\b0 \
|
18
|
+
Hopefully not nobody\
|
19
|
+
\
|
20
|
+
|
21
|
+
\b Documentation:
|
22
|
+
\b0 \
|
23
|
+
Whoever\
|
24
|
+
\
|
25
|
+
|
26
|
+
\b With special thanks to:
|
27
|
+
\b0 \
|
28
|
+
Mom\
|
29
|
+
}
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
describe "UIAppearance support" do
|
2
|
+
tests CustomAppearanceController
|
3
|
+
|
4
|
+
it "should have custom appearance on label_1" do
|
5
|
+
controller.label_1.numberOfLines.should == 3
|
6
|
+
controller.label_1.alpha.should == 0.75
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have custom appearance on container" do
|
10
|
+
controller.container.backgroundColor.should == UIColor.whiteColor
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should have different appearance on label_2" do
|
14
|
+
controller.label_2.numberOfLines.should == 2
|
15
|
+
controller.label_2.alpha.should == 0.5
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class SomeHelperClass
|
2
|
+
include Teacup::Layout
|
3
|
+
|
4
|
+
attr :container, :label
|
5
|
+
|
6
|
+
stylesheet :helper_stylesheet
|
7
|
+
|
8
|
+
def create_views
|
9
|
+
@container = layout(UIView) do
|
10
|
+
@label = layout(UILabel)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
Teacup::Stylesheet.new :helper_stylesheet do
|
18
|
+
end
|
19
|
+
|
20
|
+
Teacup::Stylesheet.new :custom_stylesheet do
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'Layout module' do
|
24
|
+
|
25
|
+
before do
|
26
|
+
@helper = SomeHelperClass.new
|
27
|
+
@stylesheet = Teacup::Stylesheet[:helper_stylesheet]
|
28
|
+
@custom_stylesheet = Teacup::Stylesheet[:custom_stylesheet]
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should return class stylesheet method' do
|
32
|
+
@helper.stylesheet.should == @stylesheet
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should allow custom stylesheet' do
|
36
|
+
@helper.stylesheet = :custom_stylesheet
|
37
|
+
@helper.stylesheet.should == @custom_stylesheet
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should custom and class stylesheets' do
|
41
|
+
another_helper = SomeHelperClass.new
|
42
|
+
another_helper.stylesheet = :custom_stylesheet
|
43
|
+
|
44
|
+
@helper.stylesheet.should == @stylesheet
|
45
|
+
another_helper.stylesheet.should == @custom_stylesheet
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should have view-creation methods' do
|
49
|
+
@helper.create_views
|
50
|
+
UIView.should === @helper.container
|
51
|
+
UILabel.should === @helper.label
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
describe "Layouts" do
|
2
|
+
|
3
|
+
it "Should be applied to UIView" do
|
4
|
+
subject = UIView.new
|
5
|
+
subject.respond_to?(:subview).should == true
|
6
|
+
subject.respond_to?(:layout).should == true
|
7
|
+
end
|
8
|
+
|
9
|
+
it "Should be applied to UIViewController" do
|
10
|
+
subject = UIViewController.new
|
11
|
+
subject.respond_to?(:subview).should == true
|
12
|
+
subject.respond_to?(:layout).should == true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "Should add a subview to a UIView" do
|
16
|
+
subject = UIView.new
|
17
|
+
subject.subviews.length.should == 0
|
18
|
+
subject.subview(UIView)
|
19
|
+
subject.subviews.length.should == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "Should add a subview to a UIViewController" do
|
23
|
+
subject = UIViewController.new
|
24
|
+
subject.view.subviews.length.should == 0
|
25
|
+
subject.subview(UIView)
|
26
|
+
subject.view.subviews.length.should == 1
|
27
|
+
end
|
28
|
+
|
29
|
+
it "Should apply styles" do
|
30
|
+
subject = UIView.new
|
31
|
+
view = subject.subview(UIView, tag: 1)
|
32
|
+
view.tag.should == 1
|
33
|
+
end
|
34
|
+
|
35
|
+
it "Should allow multiple calls" do
|
36
|
+
subject = UIView.new
|
37
|
+
view = subject.subview(UIView, tag: 1)
|
38
|
+
subject.layout(view, tag: 2)
|
39
|
+
view.tag.should == 2
|
40
|
+
end
|
41
|
+
|
42
|
+
it "Should merge hashes, like a stylesheet does" do
|
43
|
+
subject = UIView.new
|
44
|
+
view = subject.subview(UIView, layer: { opacity: 0.5 })
|
45
|
+
subject.layout(view, layer: { shadowRadius: 3 })
|
46
|
+
view.layer.opacity.should == 0.5
|
47
|
+
view.layer.shadowRadius.should == 3
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|