Skip to content

Commit

Permalink
macos helper updates (#198)
Browse files Browse the repository at this point in the history
* have RunApp handle LockOSThread
* updated examples to use RunApp API
* added doc examples in macos package
* also added MenuItem_SeparatorItem()
* used proper New methods in Menu helpers
  • Loading branch information
progrium authored Aug 23, 2023
1 parent 66531b8 commit 9a9a0d6
Show file tree
Hide file tree
Showing 16 changed files with 284 additions and 297 deletions.
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,13 @@ DarwinKit lets you work with [supported Apple frameworks](https://pkg.go.dev/git
package main

import (
"runtime"

"github.com/progrium/macdriver/objc"
"github.com/progrium/macdriver/macos"
"github.com/progrium/macdriver/macos/appkit"
"github.com/progrium/macdriver/macos/foundation"
"github.com/progrium/macdriver/macos/webkit"
)

func init() {
// ensure main is run on the startup thread
runtime.LockOSThread()
}

func main() {
// runs macOS application event loop with a callback on success
macos.RunApp(func(app appkit.Application, delegate *appkit.ApplicationDelegate) {
Expand Down
31 changes: 9 additions & 22 deletions macos/_examples/form/main.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
package main

import (
"runtime"

"github.com/progrium/macdriver/helper/layout"
"github.com/progrium/macdriver/helper/widgets"
"github.com/progrium/macdriver/macos"
"github.com/progrium/macdriver/macos/appkit"
"github.com/progrium/macdriver/macos/foundation"
"github.com/progrium/macdriver/objc"
)

// Arrange that main.main runs on main thread.
func init() {
runtime.LockOSThread()
func main() {
macos.RunApp(launched)
}

func initAndRun() {
app := appkit.Application_SharedApplication()
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
func launched(app appkit.Application, delegate *appkit.ApplicationDelegate) {
w := appkit.NewWindowWithSize(600, 400)
objc.Retain(&w)
w.SetTitle("Form")

fv := widgets.NewFormView()
Expand All @@ -38,19 +35,9 @@ func initAndRun() {
w.MakeKeyAndOrderFront(nil)
w.Center()

ad := &appkit.ApplicationDelegate{}
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
})
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
return true
})
app.SetDelegate(ad)

app.Run()
}

func main() {
initAndRun()
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
}
7 changes: 0 additions & 7 deletions macos/_examples/helloworld/main.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
package main

import (
"runtime"

"github.com/progrium/macdriver/macos"
"github.com/progrium/macdriver/macos/appkit"
"github.com/progrium/macdriver/macos/foundation"
"github.com/progrium/macdriver/macos/webkit"
"github.com/progrium/macdriver/objc"
)

func init() {
// ensure main is run on the startup thread
runtime.LockOSThread()
}

func main() {
// runs macOS application event loop with a callback on success
macos.RunApp(func(app appkit.Application, delegate *appkit.ApplicationDelegate) {
Expand Down
37 changes: 18 additions & 19 deletions macos/_examples/largetype/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,36 @@ package main
import (
"flag"
"fmt"
"runtime"
"strings"

"github.com/progrium/macdriver/macos"
"github.com/progrium/macdriver/macos/appkit"
"github.com/progrium/macdriver/macos/foundation"
"github.com/progrium/macdriver/objc"
)

func init() {
runtime.LockOSThread()
}
var (
fontName *string
text string
)

func main() {
fontName := flag.String("font", "Helvetica", "font to use")
fontName = flag.String("font", "Helvetica", "font to use")
flag.Parse()
text := strings.Join(flag.Args(), " ")

text = strings.Join(flag.Args(), " ")
if text == "" {
text = "Hello world"
}

app := appkit.Application_SharedApplication()
screen := appkit.Screen_MainScreen().Frame().Size
text = fmt.Sprintf(" %s ", text)
fmt.Println(text)

macos.RunApp(launched)
}

func launched(app appkit.Application, delegate *appkit.ApplicationDelegate) {
screen := appkit.Screen_MainScreen().Frame().Size

tr, fontSize := func() (rect foundation.Rect, size float64) {
t := appkit.NewTextViewWithFrame(rectOf(0, 0, 0, 0))
t.SetString(text)
Expand All @@ -53,8 +58,8 @@ func main() {
t.SetDrawsBackground(false)

c := appkit.NewViewWithFrame(rectOf(0, 0, 0, 0))
// deprecated...
// c.SetBackgroundColor(appkit.Color_ColorWithRedGreenBlueAlpha(0, 0, 0, 0.75))
// deprecated call, no bindings
objc.Call[objc.Void](c, objc.Sel("setBackgroundColor:"), appkit.Color_ColorWithRedGreenBlueAlpha(0, 0, 0, 0.75))
c.SetWantsLayer(true)
c.Layer().SetCornerRadius(32.0)
c.AddSubviewPositionedRelativeTo(t, appkit.WindowAbove, nil)
Expand All @@ -79,14 +84,8 @@ func main() {
appkit.Application_SharedApplication().Terminate(nil)
})

ad := &appkit.ApplicationDelegate{}
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
})
app.SetDelegate(ad)

app.Run()
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
}

func rectOf(x, y, width, height float64) foundation.Rect {
Expand Down
26 changes: 7 additions & 19 deletions macos/_examples/layout/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ package main

import (
"fmt"
"runtime"

"github.com/progrium/macdriver/helper/action"
"github.com/progrium/macdriver/helper/layout"
"github.com/progrium/macdriver/helper/widgets"
"github.com/progrium/macdriver/macos"
"github.com/progrium/macdriver/macos/appkit"
"github.com/progrium/macdriver/macos/foundation"
"github.com/progrium/macdriver/objc"
)

// Arrange that main.main runs on main thread.
func init() {
runtime.LockOSThread()
func main() {
macos.RunApp(launched)
}

func initAndRun() {
app := appkit.Application_SharedApplication()
func launched(app appkit.Application, delegate *appkit.ApplicationDelegate) {
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)

w := appkit.NewWindowWithSize(600, 400)
objc.Retain(&w)
w.SetTitle("Test Layout")

label := appkit.NewLabel("label")
Expand Down Expand Up @@ -71,19 +71,7 @@ func initAndRun() {
w.MakeKeyAndOrderFront(nil)
w.Center()

ad := &appkit.ApplicationDelegate{}
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
})
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
return true
})
app.SetDelegate(ad)

app.Run()
}

func main() {
initAndRun()
}
69 changes: 28 additions & 41 deletions macos/_examples/menu/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,43 @@ import (
"github.com/progrium/macdriver/objc"
)

// menus and tray

// Arrange that main.main runs on main thread.
func init() {
func main() {
runtime.LockOSThread()
}

func initAndRun() {
app := appkit.Application_SharedApplication()
w := appkit.NewWindowWithSize(600, 400)
w.SetTitle("Test")

// text field
textView := appkit.TextView_ScrollableTextView()
textView.SetTranslatesAutoresizingMaskIntoConstraints(false)
tv := appkit.TextViewFrom(textView.DocumentView().Ptr())
tv.SetAllowsUndo(true)
tv.SetRichText(false)
w.ContentView().AddSubview(textView)
w.ContentView().LeadingAnchor().ConstraintEqualToAnchorConstant(textView.LeadingAnchor(), -10).SetActive(true)
w.ContentView().TopAnchor().ConstraintEqualToAnchorConstant(textView.TopAnchor(), -10).SetActive(true)
w.ContentView().TrailingAnchor().ConstraintEqualToAnchorConstant(textView.TrailingAnchor(), 10).SetActive(true)
w.ContentView().BottomAnchor().ConstraintEqualToAnchorConstant(textView.BottomAnchor(), 10).SetActive(true)
delegate := &appkit.ApplicationDelegate{}
delegate.SetApplicationDidFinishLaunching(func(foundation.Notification) {
w := appkit.NewWindowWithSize(600, 400)
objc.Retain(&w)
w.SetTitle("Test")

textView := appkit.TextView_ScrollableTextView()
textView.SetTranslatesAutoresizingMaskIntoConstraints(false)
tv := appkit.TextViewFrom(textView.DocumentView().Ptr())
tv.SetAllowsUndo(true)
tv.SetRichText(false)
w.ContentView().AddSubview(textView)
w.ContentView().LeadingAnchor().ConstraintEqualToAnchorConstant(textView.LeadingAnchor(), -10).SetActive(true)
w.ContentView().TopAnchor().ConstraintEqualToAnchorConstant(textView.TopAnchor(), -10).SetActive(true)
w.ContentView().TrailingAnchor().ConstraintEqualToAnchorConstant(textView.TrailingAnchor(), 10).SetActive(true)
w.ContentView().BottomAnchor().ConstraintEqualToAnchorConstant(textView.BottomAnchor(), 10).SetActive(true)

w.MakeKeyAndOrderFront(nil)
w.Center()

w.MakeKeyAndOrderFront(nil)
w.Center()
setSystemBar(app)

ad := &appkit.ApplicationDelegate{}
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
})
ad.SetApplicationWillFinishLaunching(func(foundation.Notification) {
// should set menu bar at ApplicationWillFinishLaunching
delegate.SetApplicationWillFinishLaunching(func(foundation.Notification) {
setMainMenu(app)
})
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
return true
})
app.SetDelegate(ad)

// should set system bar after window show
setSystemBar(app)

app.SetDelegate(delegate)
app.Run()
}

Expand All @@ -69,8 +62,7 @@ func setMainMenu(app appkit.Application) {
testMenuItem := appkit.NewMenuItemWithSelector("", "", objc.Selector{})
testMenu := appkit.NewMenuWithTitle("Edit")
testMenu.AddItem(appkit.NewMenuItemWithSelector("Select All", "a", objc.Sel("selectAll:")))
// missing symbol?
//testMenu.AddItem(appkit.MenuItem_SeparatorItem())
testMenu.AddItem(appkit.MenuItem_SeparatorItem())
testMenu.AddItem(appkit.NewMenuItemWithSelector("Copy", "c", objc.Sel("copy:")))
testMenu.AddItem(appkit.NewMenuItemWithSelector("Paste", "v", objc.Sel("paste:")))
testMenu.AddItem(appkit.NewMenuItemWithSelector("Cut", "x", objc.Sel("cut:")))
Expand All @@ -81,17 +73,12 @@ func setMainMenu(app appkit.Application) {
}

func setSystemBar(app appkit.Application) {
bar := appkit.StatusBar_SystemStatusBar()
item := bar.StatusItemWithLength(appkit.VariableStatusItemLength)
button := item.Button()
button.SetTitle("TestTray")
item := appkit.StatusBar_SystemStatusBar().StatusItemWithLength(appkit.VariableStatusItemLength)
objc.Retain(&item)
item.Button().SetTitle("TestTray")

menu := appkit.NewMenuWithTitle("main")
menu.AddItem(appkit.NewMenuItemWithAction("Hide", "h", func(sender objc.Object) { app.Hide(nil) }))
menu.AddItem(appkit.NewMenuItemWithAction("Quit", "q", func(sender objc.Object) { app.Terminate(nil) }))
item.SetMenu(menu)
}

func main() {
initAndRun()
}
28 changes: 9 additions & 19 deletions macos/_examples/notification/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,34 @@ package main

import (
"runtime"
"time"

"github.com/progrium/macdriver/macos/appkit"
"github.com/progrium/macdriver/macos/foundation"
"github.com/progrium/macdriver/objc"
)

func init() {
runtime.LockOSThread()
}

func main() {
app := appkit.Application_SharedApplication()
runtime.LockOSThread()

// notifications need a unique bundleIdentifier which we can define by
// replacing the bundleIdentifier method on the default main bundle
nsbundle := foundation.Bundle_MainBundle().Class()
objc.ReplaceMethod(nsbundle, objc.Sel("bundleIdentifier"), func(_ objc.IObject) string {
return "com.example.fake2" // change this if you miss the allow notification
})

ad := &appkit.ApplicationDelegate{}
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {

objc.WithAutoreleasePool(func() {
// this API is deprecated and we currently don't generate bindings for deprecated APIs,
// so this is what using an API without bindings looks like.
notif := objc.Call[objc.Object](objc.GetClass("NSUserNotification"), objc.Sel("new"))
notif.Autorelease()
objc.Call[objc.Void](notif, objc.Sel("setTitle:"), "Hello, world!")
objc.Call[objc.Void](notif, objc.Sel("setInformativeText:"), "More text")

center := objc.Call[objc.Object](objc.GetClass("NSUserNotificationCenter"), objc.Sel("defaultUserNotificationCenter"))
objc.Call[objc.Void](center, objc.Sel("deliverNotification:"), notif)

//app.Terminate(nil)

})
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
return true
})
app.SetDelegate(ad)

app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
app.ActivateIgnoringOtherApps(true)
app.Run()
// give notification center a moment
<-time.After(1 * time.Second)
}
Loading

0 comments on commit 9a9a0d6

Please sign in to comment.