diff --git a/bar.go b/bar.go
new file mode 100644
index 0000000..d64adc2
--- /dev/null
+++ b/bar.go
@@ -0,0 +1,213 @@
+package main
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/MiracleOS-Team/desktoplib/batteryHandler"
+ "github.com/MiracleOS-Team/desktoplib/foreignToplevel"
+ "github.com/MiracleOS-Team/desktoplib/networkManagerHandler"
+ "github.com/MiracleOS-Team/desktoplib/volumeHandler"
+ "github.com/dlasky/gotk3-layershell/layershell"
+ "github.com/gotk3/gotk3/gdk"
+ "github.com/gotk3/gotk3/glib"
+ "github.com/gotk3/gotk3/gtk"
+)
+
+func getDateInfo() (string, string) {
+ hours, minutes, _ := time.Now().Clock()
+ curTimeInString := fmt.Sprintf("%d:%02d", hours, minutes)
+
+ curDay := time.Now().Day()
+ curDayName := firstN(time.Now().Weekday().String(), 3)
+ var curDayCal string
+
+ if curDay <= 5 {
+ curMonth := time.Now().Month()
+ curDayCal = fmt.Sprintf("%s. %02d %s", curDayName, curDay, curMonth)
+ } else {
+ curDayCal = fmt.Sprintf("%s. %02d", curDayName, curDay)
+ }
+ return curDayCal, curTimeInString
+}
+
+func createSidestuff() *gtk.Box {
+ sideBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
+ sideBox.SetHAlign(gtk.ALIGN_END)
+ sc, _ := sideBox.GetStyleContext()
+ sc.AddClass("sidestuff")
+
+ otherIcons, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
+ keyboardImage, _ := gtk.ImageNewFromIconName("input-keyboard-symbolic", gtk.ICON_SIZE_BUTTON)
+ sc, _ = keyboardImage.GetStyleContext()
+ sc.AddClass("keyboard")
+
+ otherIcons.PackStart(keyboardImage, false, false, 0)
+ sc, _ = otherIcons.GetStyleContext()
+ sc.AddClass("other-icons-wrapper")
+
+ statusBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
+
+ volumeIcon, err := volumeHandler.GetAudioIcon()
+
+ if err == nil {
+ volumeImage, _ := gtk.ImageNewFromIconName(volumeIcon, gtk.ICON_SIZE_BUTTON)
+ sc, _ = volumeImage.GetStyleContext()
+ sc.AddClass("sound")
+
+ statusBox.PackStart(volumeImage, false, false, 0)
+ }
+
+ networkIcon, err := networkManagerHandler.GetNetworkIcon()
+
+ if err == nil {
+ networkImage, _ := gtk.ImageNewFromIconName(networkIcon, gtk.ICON_SIZE_BUTTON)
+
+ sc, _ = networkImage.GetStyleContext()
+ sc.AddClass("network")
+
+ statusBox.PackStart(networkImage, false, false, 0)
+ }
+
+ if batteryHandler.IsBattery() {
+ batteryImage, _ := gtk.ImageNewFromIconName(batteryHandler.GetBatteryIcon(), gtk.ICON_SIZE_BUTTON)
+
+ sc, _ = batteryImage.GetStyleContext()
+ sc.AddClass("power")
+
+ statusBox.PackStart(batteryImage, false, false, 0)
+ }
+
+ sc, _ = statusBox.GetStyleContext()
+ sc.AddClass("status-icons-wrapper")
+
+ curDayCal, currUTCTimeInString := getDateInfo()
+
+ clock, _ := gtk.LabelNew(currUTCTimeInString)
+ sc, _ = clock.GetStyleContext()
+ sc.AddClass("clock-text")
+
+ dayText, _ := gtk.LabelNew(curDayCal)
+ sc, _ = dayText.GetStyleContext()
+ sc.AddClass("day-text")
+
+ glib.TimeoutAdd(uint(500), func() bool {
+ // Get new date/time info.
+ newDayCal, newTime := getDateInfo()
+
+ // Update the labels.
+ clock.SetText(newTime)
+ dayText.SetText(newDayCal)
+
+ // Return true to keep the timeout active.
+ return true
+ })
+
+ notificationButton, _ := gtk.ButtonNew()
+ notificationBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
+ sc, _ = notificationBox.GetStyleContext()
+ sc.AddClass("notification-bell-wrapper")
+
+ notificationImage, _ := gtk.ImageNewFromIconName("preferences-system-notifications-symbolic", gtk.ICON_SIZE_BUTTON)
+ sc, _ = notificationImage.GetStyleContext()
+ sc.AddClass("notification-bell")
+
+ notificationBox.PackStart(notificationImage, false, false, 0)
+ notificationButton.Add(notificationBox)
+
+ sideBox.PackStart(otherIcons, false, false, 0)
+ sideBox.PackStart(statusBox, false, false, 0)
+ sideBox.PackStart(clock, false, false, 0)
+ sideBox.PackStart(dayText, false, false, 0)
+ sideBox.PackStart(notificationButton, false, false, 0)
+
+ return sideBox
+}
+
+func createWorkspaces() *gtk.Box {
+ box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+ box.SetHAlign(gtk.ALIGN_START)
+ sc, _ := box.GetStyleContext()
+ sc.AddClass("workspaces")
+
+ toplevels, err := foreignToplevel.ListToplevels()
+ if err != nil {
+ fmt.Println("Error getting toplevels:", err)
+ return box
+ }
+
+ for _, k := range toplevels {
+ imgButton, _ := gtk.ButtonNew()
+ sc, _ := imgButton.GetStyleContext()
+ sc.AddClass("app")
+
+ img, _ := gtk.ImageNewFromIconName(k.AppID, gtk.ICON_SIZE_BUTTON)
+ imgButton.Add(img)
+ box.PackStart(imgButton, false, false, 0)
+ }
+ // Placeholder for dynamic window list
+ imgButton1, _ := gtk.ButtonNew()
+ sc, _ = imgButton1.GetStyleContext()
+ sc.AddClass("app")
+ img1, _ := gtk.ImageNewFromIconName("preferences-desktop", gtk.ICON_SIZE_BUTTON)
+ imgButton1.Add(img1)
+ box.PackStart(imgButton1, false, false, 0)
+
+ return box
+}
+
+func createMainIcons() *gtk.Box {
+ box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+ box.SetHAlign(gtk.ALIGN_CENTER)
+
+ desktopImage, _ := gtk.ImageNewFromIconName("preferences-system-windows-symbolic", gtk.ICON_SIZE_LARGE_TOOLBAR)
+ searchImage, _ := gtk.ImageNewFromIconName("system-search-symbolic", gtk.ICON_SIZE_LARGE_TOOLBAR)
+ customIcon, _ := gtk.ImageNewFromFile("images/pp.png")
+ customButton, _ := gtk.ButtonNew()
+ customButton.Add(customIcon)
+
+ customButton.Connect("clicked", func() {
+ createMainMenu().ShowAll()
+ box.Hide()
+ })
+
+ box.PackStart(desktopImage, false, false, 0)
+ box.PackStart(customButton, false, false, 0)
+ box.PackStart(searchImage, false, false, 0)
+
+ return box
+}
+
+func createBar() *gtk.Window {
+ win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
+ win.SetTitle("Main Bar")
+ win.SetDecorated(false)
+ win.SetResizable(false)
+ win.SetTypeHint(gdk.WINDOW_TYPE_HINT_DOCK)
+
+ layershell.InitForWindow(win)
+ layershell.SetNamespace(win, "miracleos")
+ layershell.SetAnchor(win, layershell.LAYER_SHELL_EDGE_LEFT, true)
+ layershell.SetAnchor(win, layershell.LAYER_SHELL_EDGE_BOTTOM, true)
+ layershell.SetAnchor(win, layershell.LAYER_SHELL_EDGE_RIGHT, true)
+
+ layershell.SetLayer(win, layershell.LAYER_SHELL_LAYER_TOP)
+ layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_TOP, 0)
+ layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_LEFT, 0)
+ layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_RIGHT, 0)
+
+ layershell.SetExclusiveZone(win, 75)
+ layershell.SetKeyboardMode(win, layershell.LAYER_SHELL_KEYBOARD_MODE_NONE)
+ disp, _ := gdk.DisplayGetDefault()
+ mon, _ := disp.GetMonitor(0)
+ layershell.SetMonitor(win, mon)
+
+ box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+ sc, _ := box.GetStyleContext()
+ sc.AddClass("bar")
+ box.PackStart(createWorkspaces(), false, false, 0)
+ box.SetCenterWidget(createMainIcons())
+ box.PackEnd(createSidestuff(), false, false, 0)
+ win.Add(box)
+ return win
+}
diff --git a/desktop.css b/desktop.css
index ccf684d..74454ce 100644
--- a/desktop.css
+++ b/desktop.css
@@ -279,4 +279,8 @@
.status-icons-wrapper image {
margin: 5px;
- }
\ No newline at end of file
+ }
+
+ .workspaces * {
+ margin: 0px;
+ }
diff --git a/go.mod b/go.mod
index eb371cb..a0ad624 100644
--- a/go.mod
+++ b/go.mod
@@ -3,13 +3,28 @@ module github.com/MiracleOS-Team/desktop
go 1.22.2
require (
- github.com/MiracleOS-Team/libxdg-go v0.0.0-20250130123149-66a2b3e59a66
+ github.com/MiracleOS-Team/desktoplib v0.0.0-20250204155824-a42d5b7c24e3
+ github.com/MiracleOS-Team/libxdg-go v0.0.0-20250203122932-0d6a9fc71582
+ github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774
github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56
)
require (
github.com/cli/safeexec v1.0.1 // indirect
- golang.org/x/text v0.21.0 // indirect
+ github.com/distatus/battery v0.11.0 // indirect
+ github.com/gdamore/encoding v1.0.0 // indirect
+ github.com/gdamore/tcell v1.4.0 // indirect
+ github.com/gek64/displayController v1.0.2 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/godbus/dbus/v5 v5.1.0 // indirect
+ github.com/itchyny/volume-go v0.2.2 // indirect
+ github.com/jfreymuth/pulse v0.1.1 // indirect
+ github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
+ github.com/mattn/go-runewidth v0.0.7 // indirect
+ github.com/moutend/go-wca v0.3.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
+ howett.net/plist v1.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index be21494..4c5877f 100644
--- a/go.sum
+++ b/go.sum
@@ -1,9 +1,17 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/MiracleOS-Team/desktoplib v0.0.0-20250203164533-9daac46041b5 h1:bnMP6ciWaT2zl+IJcWDfwhDFbp9iF4vZ9g50HRQkWC8=
+github.com/MiracleOS-Team/desktoplib v0.0.0-20250203164533-9daac46041b5/go.mod h1:LvzdmHbq2om/X8sPOcR3faqsZQRHTVMCm58NFp2aLIU=
+github.com/MiracleOS-Team/desktoplib v0.0.0-20250203213240-ff0177e4ccaa h1:yAqSw/ahPqVO7O5LxpzJpNuZlW5Q366BKUwZWIJ2nDE=
+github.com/MiracleOS-Team/desktoplib v0.0.0-20250203213240-ff0177e4ccaa/go.mod h1:LvzdmHbq2om/X8sPOcR3faqsZQRHTVMCm58NFp2aLIU=
+github.com/MiracleOS-Team/desktoplib v0.0.0-20250204155824-a42d5b7c24e3 h1:+UZtfbdcpSCXIap83dOHxWcMOqc42jCpYepfidv6xGY=
+github.com/MiracleOS-Team/desktoplib v0.0.0-20250204155824-a42d5b7c24e3/go.mod h1:lsr1apHlN/KIBNQdH2ngannvIIBKnYRvyo8oCgBoaVE=
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250126160842-bc18282c37ee h1:jsl3imeBR+qACjnTzGHJt1zrvrkW5MkHyFFpsmYnzxk=
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250126160842-bc18282c37ee/go.mod h1:mKskdRQzPihHpgc1aUN06dlR2ECTxQWgPzOY3u2To+I=
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250130123149-66a2b3e59a66 h1:zax0cvv63QOakMKGH4p1UN9UfVW9bRHEe1Q2GGRPt00=
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250130123149-66a2b3e59a66/go.mod h1:mKskdRQzPihHpgc1aUN06dlR2ECTxQWgPzOY3u2To+I=
+github.com/MiracleOS-Team/libxdg-go v0.0.0-20250203122932-0d6a9fc71582 h1:Ce5u6O6M1586/JQxVvGr/GCClbxUJbtRPckg4ZfFawY=
+github.com/MiracleOS-Team/libxdg-go v0.0.0-20250203122932-0d6a9fc71582/go.mod h1:mKskdRQzPihHpgc1aUN06dlR2ECTxQWgPzOY3u2To+I=
github.com/bep/godartsass v1.2.0 h1:E2VvQrxAHAFwbjyOIExAMmogTItSKodoKuijNrGm5yU=
github.com/bep/godartsass v1.2.0/go.mod h1:6LvK9RftsXMxGfsA0LDV12AGc4Jylnu6NgHL+Q5/pE8=
github.com/bep/godartsass/v2 v2.3.2 h1:meuc76J1C1soSCAnlnJRdGqJ5S4m6/GW+8hmOe9tOog=
@@ -15,10 +23,27 @@ github.com/cli/safeexec v1.0.1 h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00=
github.com/cli/safeexec v1.0.1/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/distatus/battery v0.11.0 h1:KJk89gz90Iq/wJtbjjM9yUzBXV+ASV/EG2WOOL7N8lc=
+github.com/distatus/battery v0.11.0/go.mod h1:KmVkE8A8hpIX4T78QRdMktYpEp35QfOL8A8dwZBxq2k=
+github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774 h1:o87OVL4olQBlVwN3+NSVQpS6gj9FWUYtxOfHXWZigUE=
+github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774/go.mod h1:JHLx2Wz4mAPVwn4PFhC69ydwyHP4A3wQvlg7HKVVc1U=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns=
github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
+github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
+github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU=
+github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0=
+github.com/gek64/displayController v1.0.2 h1:xx1Um0aBResxS6eVjhEXU4U0LqjH723E9UPTDsC/j7M=
+github.com/gek64/displayController v1.0.2/go.mod h1:N9v4SImJeiH2Ep/epdg2OvGPeRhqVRthu04WhhF/S6Q=
+github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -36,8 +61,14 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/gotk3/gotk3 v0.6.1/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56 h1:eR+xxC8qqKuPMTucZqaklBxLIT7/4L7dzhlwKMrDbj8=
github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
+github.com/itchyny/volume-go v0.2.2 h1:v+FX58TV+g/IelerseqMO1LmdRoIuSS2uB26Ggljzx0=
+github.com/itchyny/volume-go v0.2.2/go.mod h1:0JOgisElMS/72B2DI4ha8CH2JXPUPTbe1agjk8jTU3s=
+github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jfreymuth/pulse v0.1.1 h1:9WLNBNCijmtZ14ZJpatgJPu/NjwAl3TIKItSFnTh+9A=
+github.com/jfreymuth/pulse v0.1.1/go.mod h1:cpYspI6YljhkUf1WLXLLDmeaaPFc3CnGLjDZf9dZ4no=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
@@ -45,6 +76,14 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
+github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/moutend/go-wca v0.2.0 h1:AEzY6ltC5zPCldKyMYdyXv3TaLqwxSW1TIradqNqRpU=
+github.com/moutend/go-wca v0.2.0/go.mod h1:L/ka++dPvkHYz0UuQ/PIQ3aTuecoXOIM1RSAesh6RYU=
+github.com/moutend/go-wca v0.3.0 h1:IzhsQ44zBzMdT42xlBjiLSVya9cPYOoKx9E+yXVhFo8=
+github.com/moutend/go-wca v0.3.0/go.mod h1:7VrPO512jnjFGJ6rr+zOoCfiYjOHRPNfbttJuxAurcw=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
@@ -63,9 +102,19 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10=
+golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
+golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -91,9 +140,15 @@ google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
+howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
+howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
+howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
diff --git a/images/logo-rs.png b/images/logo-rs.png
new file mode 100644
index 0000000..2b2aa08
Binary files /dev/null and b/images/logo-rs.png differ
diff --git a/images/logo.png b/images/logo.png
new file mode 100644
index 0000000..2318084
Binary files /dev/null and b/images/logo.png differ
diff --git a/images/pp.png b/images/pp.png
new file mode 100644
index 0000000..28442d0
Binary files /dev/null and b/images/pp.png differ
diff --git a/main.go b/main.go
index 354e828..01d31d8 100644
--- a/main.go
+++ b/main.go
@@ -1,22 +1,19 @@
package main
import (
- "fmt"
"log"
"os"
- "sort"
- "github.com/MiracleOS-Team/libxdg-go/desktopFiles"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
)
func loadCSS() {
-
// Load CSS into GTK
provider, _ := gtk.CssProviderNew()
//err = provider.LoadFromData(css)
err := provider.LoadFromPath("/opt/miracleos-software/desktop/desktop.css")
+ //err := provider.LoadFromPath("desktop.css")
if err != nil {
log.Println("Failed to load CSS into GTK:", err)
return
@@ -58,40 +55,6 @@ func scalePixbuf(pixbuf *gdk.Pixbuf, maxWidth, maxHeight int) *gdk.Pixbuf {
return scaledPixbuf
}
-func createAppGroup(apps []desktopFiles.DesktopFile) *gtk.Box {
- group, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
- for _, app := range apps {
- buttonBox, _ := gtk.ButtonNew()
- appBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
- sc, _ := appBox.GetStyleContext()
- sc.AddClass("mm_applist_app")
-
- pixbuf, err := gdk.PixbufNewFromFile(app.Icon) // Replace with your image path
- if err == nil {
- // Define max size
- maxWidth := 16
- maxHeight := 16
-
- scaledPixbuf := scalePixbuf(pixbuf, maxWidth, maxHeight)
-
- icon, _ := gtk.ImageNewFromPixbuf(scaledPixbuf)
- appBox.PackStart(icon, false, false, 5)
- }
-
- label, _ := gtk.LabelNew(app.Name)
-
- appBox.PackStart(label, false, false, 5)
- buttonBox.Add(appBox)
- buttonBox.Connect("button-press-event", func() {
- fmt.Println("Clicked on", app.Name)
- go desktopFiles.ExecuteDesktopFile(app, []string{}, "")
- })
- group.PackStart(buttonBox, false, false, 5)
-
- }
- return group
-}
-
func firstN(s string, n int) string {
i := 0
for j := range s {
@@ -103,185 +66,14 @@ func firstN(s string, n int) string {
return s
}
-func createAppList() *gtk.ScrolledWindow {
- scroll, _ := gtk.ScrolledWindowNew(nil, nil)
- scroll.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- vbox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
-
- apps, _ := desktopFiles.ListAllApplications()
-
- categories := map[string][]desktopFiles.DesktopFile{}
-
- for _, app := range apps {
- if _, ok := categories[firstN(app.Name, 1)]; !ok {
- categories[firstN(app.Name, 1)] = []desktopFiles.DesktopFile{}
- }
- categories[firstN(app.Name, 1)] = append(categories[firstN(app.Name, 1)], app)
- }
-
- // Sort categories alphabetically
- sortedCategories := make([]string, 0, len(categories))
- for category := range categories {
- sortedCategories = append(sortedCategories, category)
- }
- sort.Strings(sortedCategories)
-
- for _, category := range sortedCategories {
- label, _ := gtk.LabelNew(category)
- label.SetMarkup("" + category + "")
- label.SetXAlign(0)
- vbox.PackStart(label, false, false, 5)
-
- // Sort applications within each category
- appList := categories[category]
- sortedAppNames := make([]string, 0, len(appList))
- for _, app := range appList {
- sortedAppNames = append(sortedAppNames, app.Name)
- }
- sort.Strings(sortedAppNames)
-
- sortedApps := make([]desktopFiles.DesktopFile, 0, len(appList))
- for _, appName := range sortedAppNames {
- for _, app := range appList {
- if app.Name == appName {
- sortedApps = append(sortedApps, app)
- }
- }
- }
-
- vbox.PackStart(createAppGroup(sortedApps), false, false, 5)
- }
-
- scroll.Add(vbox)
- return scroll
-}
-
-func createUserInfo() *gtk.Box {
- userBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
- userImage, _ := gtk.ImageNewFromFile("images/pp.png")
- userLabel, _ := gtk.LabelNew("Abdi\nanonymous@gmail.com")
- userLabel.SetXAlign(0)
- userBox.PackStart(userImage, false, false, 5)
- userBox.PackStart(userLabel, false, false, 5)
- return userBox
-}
-
-func createPowerButtons() *gtk.Box {
- powerBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
- shutdownBtn, _ := gtk.ButtonNewWithLabel("Shutdown")
- shutdownBtn.Connect("clicked", func() {
- os.Exit(0)
- })
- powerBox.PackEnd(shutdownBtn, false, false, 5)
- return powerBox
-}
-
-func createMainMenu() *gtk.Window {
- win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
- win.SetTitle("Main Menu")
- win.SetDefaultSize(600, 600)
- win.SetDecorated(false)
- win.Move(0, 0)
- win.SetResizable(false)
- win.SetTypeHint(gdk.WINDOW_TYPE_HINT_DOCK)
-
- screen, _ := gdk.ScreenGetDefault()
-
- // Get the primary monitor dimensions
- rootWindow, _ := screen.GetRootWindow()
-
- rootWindow.WindowGetHeight()
-
- // Get the monitor width and height
- monitorWidth := rootWindow.WindowGetWidth()
- monitorHeight := rootWindow.WindowGetHeight()
-
- fmt.Println(monitorWidth)
- fmt.Println(monitorHeight)
-
- // Calculate the center position
- windowWidth, windowHeight := win.GetSize()
- x := (monitorWidth - windowWidth) / 2
- y := (monitorHeight - windowHeight*2)
-
- fmt.Println(x)
- fmt.Println(y)
- win.Move(x, y)
-
- mainBox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 10)
- sc, _ := mainBox.GetStyleContext()
- sc.AddClass("mm_menu_m2")
-
- topBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
- sc, _ = topBox.GetStyleContext()
- sc.AddClass("mm_toppart")
-
- searchEntry, _ := gtk.EntryNew()
- searchEntry.SetPlaceholderText("Search Anything")
- sc, _ = searchEntry.GetStyleContext()
- sc.AddClass("mos-input")
- searchEntry.SetHAlign(gtk.ALIGN_CENTER)
- searchEntry.SetSizeRequest(100, -1)
- topBox.PackStart(searchEntry, true, true, 5)
-
- contentBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
-
- appList := createAppList()
- sc, _ = appList.GetStyleContext()
- sc.AddClass("mm_tab")
-
- fastApps := createPlaceholder("Most Used")
- sc, _ = fastApps.GetStyleContext()
- sc.AddClass("mm_tab")
-
- otherTab := createPlaceholder("Other")
- sc, _ = otherTab.GetStyleContext()
- sc.AddClass("mm_tab")
-
- appList.SetSizeRequest(300, 600)
- fastApps.SetSizeRequest(300, 600)
- otherTab.SetSizeRequest(300, 600)
-
- contentBox.PackStart(appList, false, false, 10)
- contentBox.PackStart(fastApps, false, false, 10)
- contentBox.PackStart(otherTab, false, false, 10)
-
- mainBox.PackStart(topBox, true, true, 10)
- mainBox.PackStart(contentBox, true, true, 10)
-
- userInfo := createUserInfo()
- sc, _ = userInfo.GetStyleContext()
- sc.AddClass("mm_profileinfo")
-
- powerButtons := createPowerButtons()
- sc, _ = userInfo.GetStyleContext()
- sc.AddClass("mm_managingicons")
-
- bottomBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
- bottomBox.PackStart(userInfo, false, false, 10)
- bottomBox.PackEnd(powerButtons, false, false, 10)
- sc, _ = bottomBox.GetStyleContext()
- sc.AddClass("mm_bottompart")
- mainBox.PackStart(bottomBox, false, false, 10)
-
- win.Add(mainBox)
- return win
-}
-
-func createPlaceholder(name string) *gtk.Box {
- box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 10)
- label, _ := gtk.LabelNew(name + "\nThis functionality isn't available for now")
- box.PackStart(label, false, false, 10)
- return box
-}
-
func main() {
gtk.Init(&os.Args)
loadCSS()
- win := createMainMenu()
- win.Connect("destroy", func() {
- gtk.MainQuit()
- })
- win.ShowAll()
+ //win := createMainMenu()
+ //win.ShowAll()
+
+ bar := createBar()
+ bar.ShowAll()
+
gtk.Main()
}
diff --git a/mainMenu.go b/mainMenu.go
new file mode 100644
index 0000000..2e6aec6
--- /dev/null
+++ b/mainMenu.go
@@ -0,0 +1,208 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "sort"
+
+ "github.com/MiracleOS-Team/libxdg-go/desktopFiles"
+ "github.com/dlasky/gotk3-layershell/layershell"
+ "github.com/gotk3/gotk3/gdk"
+ "github.com/gotk3/gotk3/gtk"
+)
+
+func createAppGroup(apps []desktopFiles.DesktopFile) *gtk.Box {
+ group, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
+ for _, app := range apps {
+ buttonBox, _ := gtk.ButtonNew()
+ appBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
+ sc, _ := appBox.GetStyleContext()
+ sc.AddClass("mm_applist_app")
+
+ pixbuf, err := gdk.PixbufNewFromFile(app.Icon) // Replace with your image path
+ if err == nil {
+ // Define max size
+ maxWidth := 16
+ maxHeight := 16
+
+ scaledPixbuf := scalePixbuf(pixbuf, maxWidth, maxHeight)
+
+ icon, _ := gtk.ImageNewFromPixbuf(scaledPixbuf)
+ appBox.PackStart(icon, false, false, 5)
+ }
+
+ label, _ := gtk.LabelNew(app.Name)
+
+ appBox.PackStart(label, false, false, 5)
+ buttonBox.Add(appBox)
+ buttonBox.Connect("button-press-event", func() {
+ fmt.Println("Clicked on", app.Name)
+ go desktopFiles.ExecuteDesktopFile(app, []string{}, "")
+ })
+ group.PackStart(buttonBox, false, false, 5)
+
+ }
+ return group
+}
+
+func createAppList() *gtk.ScrolledWindow {
+ scroll, _ := gtk.ScrolledWindowNew(nil, nil)
+ scroll.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ vbox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
+
+ apps, _ := desktopFiles.ListAllApplications()
+
+ categories := map[string][]desktopFiles.DesktopFile{}
+
+ for _, app := range apps {
+ if _, ok := categories[firstN(app.Name, 1)]; !ok {
+ categories[firstN(app.Name, 1)] = []desktopFiles.DesktopFile{}
+ }
+ categories[firstN(app.Name, 1)] = append(categories[firstN(app.Name, 1)], app)
+ }
+
+ // Sort categories alphabetically
+ sortedCategories := make([]string, 0, len(categories))
+ for category := range categories {
+ sortedCategories = append(sortedCategories, category)
+ }
+ sort.Strings(sortedCategories)
+
+ for _, category := range sortedCategories {
+ label, _ := gtk.LabelNew(category)
+ label.SetMarkup("" + category + "")
+ label.SetXAlign(0)
+ vbox.PackStart(label, false, false, 5)
+
+ // Sort applications within each category
+ appList := categories[category]
+ sortedAppNames := make([]string, 0, len(appList))
+ for _, app := range appList {
+ sortedAppNames = append(sortedAppNames, app.Name)
+ }
+ sort.Strings(sortedAppNames)
+
+ sortedApps := make([]desktopFiles.DesktopFile, 0, len(appList))
+ for _, appName := range sortedAppNames {
+ for _, app := range appList {
+ if app.Name == appName {
+ sortedApps = append(sortedApps, app)
+ }
+ }
+ }
+
+ vbox.PackStart(createAppGroup(sortedApps), false, false, 5)
+ }
+
+ scroll.Add(vbox)
+ return scroll
+}
+
+func createUserInfo() *gtk.Box {
+ userBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+ userImage, _ := gtk.ImageNewFromFile("images/pp.png")
+ userLabel, _ := gtk.LabelNew("Abdi\nanonymous@gmail.com")
+ userLabel.SetXAlign(0)
+ userBox.PackStart(userImage, false, false, 5)
+ userBox.PackStart(userLabel, false, false, 5)
+ return userBox
+}
+
+func createPowerButtons() *gtk.Box {
+ powerBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+ shutdownBtn, _ := gtk.ButtonNewWithLabel("Shutdown")
+ shutdownBtn.Connect("clicked", func() {
+ os.Exit(0)
+ })
+ powerBox.PackEnd(shutdownBtn, false, false, 5)
+ return powerBox
+}
+
+func createMainMenu() *gtk.Window {
+ win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
+ win.SetTitle("Main Menu")
+ win.SetDefaultSize(600, 600)
+ win.SetDecorated(false)
+ win.SetResizable(false)
+ win.SetTypeHint(gdk.WINDOW_TYPE_HINT_DOCK)
+
+ layershell.InitForWindow(win)
+ layershell.SetNamespace(win, "miracleos")
+
+ layershell.SetAnchor(win, layershell.LAYER_SHELL_EDGE_BOTTOM, true)
+
+ layershell.SetLayer(win, layershell.LAYER_SHELL_LAYER_OVERLAY)
+ layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_TOP, 0)
+ layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_LEFT, 0)
+ layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_RIGHT, 0)
+
+ disp, _ := gdk.DisplayGetDefault()
+ mon, _ := disp.GetMonitor(0)
+ layershell.SetMonitor(win, mon)
+
+ mainBox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 10)
+ sc, _ := mainBox.GetStyleContext()
+ sc.AddClass("mm_menu_m2")
+
+ topBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+ sc, _ = topBox.GetStyleContext()
+ sc.AddClass("mm_toppart")
+
+ searchEntry, _ := gtk.EntryNew()
+ searchEntry.SetPlaceholderText("Search Anything")
+ sc, _ = searchEntry.GetStyleContext()
+ sc.AddClass("mos-input")
+ searchEntry.SetHAlign(gtk.ALIGN_CENTER)
+ searchEntry.SetSizeRequest(100, -1)
+ topBox.PackStart(searchEntry, true, true, 5)
+
+ contentBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+
+ appList := createAppList()
+ sc, _ = appList.GetStyleContext()
+ sc.AddClass("mm_tab")
+
+ fastApps := createPlaceholder("Most Used")
+ sc, _ = fastApps.GetStyleContext()
+ sc.AddClass("mm_tab")
+
+ otherTab := createPlaceholder("Other")
+ sc, _ = otherTab.GetStyleContext()
+ sc.AddClass("mm_tab")
+
+ appList.SetSizeRequest(300, 600)
+ fastApps.SetSizeRequest(300, 600)
+ otherTab.SetSizeRequest(300, 600)
+
+ contentBox.PackStart(appList, false, false, 10)
+ contentBox.PackStart(fastApps, false, false, 10)
+ contentBox.PackStart(otherTab, false, false, 10)
+
+ mainBox.PackStart(topBox, true, true, 10)
+ mainBox.PackStart(contentBox, true, true, 10)
+
+ userInfo := createUserInfo()
+ sc, _ = userInfo.GetStyleContext()
+ sc.AddClass("mm_profileinfo")
+
+ powerButtons := createPowerButtons()
+ sc, _ = userInfo.GetStyleContext()
+ sc.AddClass("mm_managingicons")
+
+ bottomBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
+ bottomBox.PackStart(userInfo, false, false, 10)
+ bottomBox.PackEnd(powerButtons, false, false, 10)
+ sc, _ = bottomBox.GetStyleContext()
+ sc.AddClass("mm_bottompart")
+ mainBox.PackStart(bottomBox, false, false, 10)
+
+ win.Add(mainBox)
+ return win
+}
+
+func createPlaceholder(name string) *gtk.Box {
+ box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 10)
+ label, _ := gtk.LabelNew(name + "\nThis functionality isn't available for now")
+ box.PackStart(label, false, false, 10)
+ return box
+}