Skip to content

Commit

Permalink
Merge pull request #4 from demarey/menu-support
Browse files Browse the repository at this point in the history
add an API to easily build Mac Os menus
  • Loading branch information
estebanlm authored Apr 26, 2024
2 parents ab6ec69 + f4a3560 commit ad291c8
Show file tree
Hide file tree
Showing 33 changed files with 1,057 additions and 27 deletions.
3 changes: 2 additions & 1 deletion src/BaselineOfObjCBridge/BaselineOfObjCBridge.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ BaselineOfObjCBridge >> baseline: spec [
<baseline>

spec for: #common do: [
spec package: 'ObjectiveC' ].
spec package: 'ObjectiveC'.
spec package: 'ObjectiveC-Cocoa'].
]
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/CocoaApplication.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Class {
#pools : [
'CocoaConstants'
],
#category : #ObjectiveC-Cocoa
#category : #'ObjectiveC-Cocoa'
}

{ #category : #accessing }
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/CocoaConstants.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Class {
'NSSquareStatusItemLength',
'NSVariableStatusItemLength'
],
#category : #ObjectiveC-Cocoa
#category : #'ObjectiveC-Cocoa'
}

{ #category : #'class initialization' }
Expand Down
138 changes: 138 additions & 0 deletions src/ObjectiveC-Cocoa/CocoaMenu.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"
I represent an item of a Cocoa Menu.
I can hold items or submenus.
"
Class {
#name : #CocoaMenu,
#superclass : #Object,
#instVars : [
'nsMenu',
'items',
'title',
'nsTitle',
'menuItem'
],
#classVars : [
'MainMenu'
],
#category : #'ObjectiveC-Cocoa-Menus'
}

{ #category : #'instance creation' }
CocoaMenu class >> with: aNSMenu [

^ self new
setMenu: aNSMenu;
yourself
]

{ #category : #adding }
CocoaMenu >> addItemWithTitle: aString action: aBlock [

^ self addItemWithTitle: aString action: aBlock shortcut: ''
]

{ #category : #adding }
CocoaMenu >> addItemWithTitle: aTitle action: actionBlock shortcut: shortcutString [

items add: (CocoaMenuItem new
title: aTitle;
action: actionBlock;
shortcut: shortcutString;
yourself)
]

{ #category : #adding }
CocoaMenu >> addSeparator [

items add: CocoaMenuSeparator new
]

{ #category : #adding }
CocoaMenu >> addServicesMenu [

items add: CocoaServicesMenu new
]

{ #category : #adding }
CocoaMenu >> addSubmenu: aTitle with: builderBlock [

| menu |
menu := self class new.
menu title: aTitle.
builderBlock value: menu.
items add: menu.
^ menu
]

{ #category : #private }
CocoaMenu >> addToMenu: aCocoaMenu [
<ignoreNotImplementedSelectors: #(#addItemWithTitle:action:keyEquivalent: #setSubmenu:forItem:)>

self buildNSMenu.
menuItem := aCocoaMenu nsMenu
addItemWithTitle: nsTitle
action: ObjCObject nil
keyEquivalent: '' asNSString.

aCocoaMenu nsMenu setSubmenu: nsMenu forItem: menuItem.

]

{ #category : #configuring }
CocoaMenu >> beMainMenu [

self buildNSMenu.
#NSApplication inObjC sharedApplication setMainMenu: nsMenu.
MainMenu := self
]

{ #category : #private }
CocoaMenu >> buildNSMenu [
<ignoreNotImplementedSelectors: #(#initWithTitle:)>

nsTitle := (title ifNil: [ '' ]) asNSString.
nsMenu := #NSMenu inObjC alloc initWithTitle: nsTitle.
items do: [ :item | item addToMenu: self ].
^ nsMenu
]

{ #category : #initialization }
CocoaMenu >> initialize [

super initialize.
items := OrderedCollection new
]

{ #category : #accessing }
CocoaMenu >> nsMenu [

^ nsMenu
]

{ #category : #printing }
CocoaMenu >> printOn: aStream [
aStream << self class name << '(' << (title ifNil: [ '' ]) << ')'
]

{ #category : #removing }
CocoaMenu >> removeAllItems [

nsMenu removeAllItems.

self flag: 'TODO: release ObjC menu items'.
items := OrderedCollection new.

]

{ #category : #private }
CocoaMenu >> setMenu: aNSMenu [

nsMenu := aNSMenu
]

{ #category : #accessing }
CocoaMenu >> title: aString [

title := aString
]
57 changes: 57 additions & 0 deletions src/ObjectiveC-Cocoa/CocoaMenuItem.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"
I represent an item of a Cocoa menu.
I can hold menu items or submenus.
"
Class {
#name : #CocoaMenuItem,
#superclass : #Object,
#instVars : [
'action',
'shortcut',
'title',
'target',
'nsTitle',
'nsShortcut',
'menuItem'
],
#category : #'ObjectiveC-Cocoa-Menus'
}

{ #category : #accessing }
CocoaMenuItem >> action: aBlock [

action := aBlock
]

{ #category : #adding }
CocoaMenuItem >> addToMenu: aCocoaMenu [
<ignoreNotImplementedSelectors: #(#addItemWithTitle:action:keyEquivalent: #setTarget: #setEnabled:)>

nsTitle := title asNSString.
nsShortcut := shortcut asNSString.

menuItem := aCocoaMenu nsMenu
addItemWithTitle: nsTitle
action: #execute asObjCSelector
keyEquivalent: nsShortcut.

target := CocoaMenuTarget new
block: action;
yourself.
ObjCProxyClass newFor: target.
menuItem setTarget: target.
menuItem setEnabled: true

]

{ #category : #accessing }
CocoaMenuItem >> shortcut: aString [

shortcut := aString
]

{ #category : #accessing }
CocoaMenuItem >> title: aString [

title := aString
]
17 changes: 17 additions & 0 deletions src/ObjectiveC-Cocoa/CocoaMenuSeparator.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"
A Cocoa menu separator. I'm also a menu item.
"
Class {
#name : #CocoaMenuSeparator,
#superclass : #Object,
#category : #'ObjectiveC-Cocoa-Menus'
}

{ #category : #adding }
CocoaMenuSeparator >> addToMenu: aCocoaMenu [
<ignoreNotImplementedSelectors: #(#separatorItem)>

| separator |
separator := #NSMenuItem inObjC separatorItem.
aCocoaMenu nsMenu addItem: separator
]
43 changes: 43 additions & 0 deletions src/ObjectiveC-Cocoa/CocoaMenuTarget.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"
I represent a Cocoa menu target, i.e. the ObjectiveC object that will receive the callbacks.
"
Class {
#name : #CocoaMenuTarget,
#superclass : #Object,
#instVars : [
'proxy',
'block'
],
#category : #'ObjectiveC-Cocoa-Menus'
}

{ #category : #accessing }
CocoaMenuTarget >> block [

^ block
]

{ #category : #accessing }
CocoaMenuTarget >> block: anObject [

block := anObject
]

{ #category : #execution }
CocoaMenuTarget >> execute [
<objCSignature: #(void ())>

block value
]

{ #category : #accessing }
CocoaMenuTarget >> proxy [

^ proxy
]

{ #category : #accessing }
CocoaMenuTarget >> proxy: anObject [

proxy := anObject
]
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/CocoaMorphView.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Class {
#instVars : [
'morph'
],
#category : #ObjectiveC-Cocoa
#category : #'ObjectiveC-Cocoa'
}

{ #category : #private }
Expand Down
42 changes: 42 additions & 0 deletions src/ObjectiveC-Cocoa/CocoaServicesMenu.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"
I represent the Mac os ""Services"" menu.
You can use me to add a ""Services"" entry to your app menu.
"
Class {
#name : #CocoaServicesMenu,
#superclass : #CocoaMenu,
#category : #'ObjectiveC-Cocoa-Menus'
}

{ #category : #configuring }
CocoaServicesMenu >> beServicesMenu [
<ignoreNotImplementedSelectors: #(#setServicesMenu:)>

#NSApplication inObjC sharedApplication setServicesMenu: nsMenu
]

{ #category : #private }
CocoaServicesMenu >> buildNSMenu [

nsMenu := self servicesMenu.
nsMenu isNull
ifTrue: [
super buildNSMenu.
self beServicesMenu ]
ifFalse: [ nsTitle := title asNSString ].
^ nsMenu
]

{ #category : #initialization }
CocoaServicesMenu >> initialize [

super initialize.
title := 'Services'
]

{ #category : #accessing }
CocoaServicesMenu >> servicesMenu [
"Get the Application services menu if set or null"

^ #NSApplication inObjC sharedApplication servicesMenu
]
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/CocoaViewController.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Class {
#pools : [
'CocoaConstants'
],
#category : #ObjectiveC-Cocoa
#category : #'ObjectiveC-Cocoa'
}

{ #category : #private }
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/CocoaWindowController.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Class {
#pools : [
'CocoaConstants'
],
#category : #ObjectiveC-Cocoa
#category : #'ObjectiveC-Cocoa'
}

{ #category : #private }
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/CoreGraphicsLibrary.class.st
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Class {
#name : #CoreGraphicsLibrary,
#superclass : #FFILibrary,
#category : #ObjectiveC-Cocoa
#category : #'ObjectiveC-Cocoa'
}

{ #category : #'accessing platform' }
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/MacOSXAlertDelegate.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Class {
#instVars : [
'proxy'
],
#category : #ObjectiveC-Cocoa-Examples
#category : #'ObjectiveC-Cocoa-Examples'
}

{ #category : #example }
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/MacOSXWindowDelegate.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Class {
#instVars : [
'proxy'
],
#category : #ObjectiveC-Cocoa-Examples
#category : #'ObjectiveC-Cocoa-Examples'
}

{ #category : #example }
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/NSPoint.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Class {
'OFFSET_X',
'OFFSET_Y'
],
#category : #ObjectiveC-Cocoa-Structure
#category : #'ObjectiveC-Cocoa-Structure'
}

{ #category : #'field definition' }
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectiveC-Cocoa/NSRect.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Class {
'OFFSET_X',
'OFFSET_Y'
],
#category : #ObjectiveC-Cocoa-Structure
#category : #'ObjectiveC-Cocoa-Structure'
}

{ #category : #'field definition' }
Expand Down
Loading

0 comments on commit ad291c8

Please sign in to comment.