Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 50105c242a | |||
| 6e8d97f29b | |||
| c8e0f08aae | |||
| 916f9cc79b |
@@ -0,0 +1 @@
|
|||||||
|
testing/
|
||||||
@@ -1,319 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/gdk"
|
|
||||||
"github.com/gotk3/gotk3/gtk"
|
|
||||||
)
|
|
||||||
|
|
||||||
type app struct {
|
|
||||||
name string
|
|
||||||
cat string
|
|
||||||
appimg []string
|
|
||||||
lin []string
|
|
||||||
ex []string
|
|
||||||
icon *gdk.Pixbuf
|
|
||||||
dir string
|
|
||||||
ini *os.File
|
|
||||||
wine bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *app) getTreeIter(store *gtk.TreeStore) *gtk.TreeIter {
|
|
||||||
it := store.Append(nil)
|
|
||||||
scaled, _ := a.icon.ScaleSimple(32, 32, gdk.INTERP_HYPER)
|
|
||||||
store.SetValue(it, 0, scaled)
|
|
||||||
if portableHide {
|
|
||||||
store.SetValue(it, 1, strings.TrimSuffix(a.name, "Portable"))
|
|
||||||
} else {
|
|
||||||
store.SetValue(it, 1, a.name)
|
|
||||||
}
|
|
||||||
if len(a.ex) > 1 {
|
|
||||||
if wine {
|
|
||||||
for _, v := range a.ex {
|
|
||||||
i := store.Append(it)
|
|
||||||
store.SetValue(i, 1, v)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, v := range a.lin {
|
|
||||||
i := store.Append(it)
|
|
||||||
store.SetValue(i, 1, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *app) launch() {
|
|
||||||
if len(a.ex) == 1 {
|
|
||||||
if wine {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if !contains(a.lin, a.ex[0]) {
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[0]), ".appimage") {
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[0]+".home", 0777)
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[0]+".config", 0777)
|
|
||||||
}
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
} else {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[0]), ".appimage") {
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[0]+".home", 0777)
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[0]+".config", 0777)
|
|
||||||
}
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[0]+"\"")
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if wine {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if len(a.lin) == 0 {
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[0]+"\"")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var ind int
|
|
||||||
for i, v := range a.lin {
|
|
||||||
if strings.HasSuffix(v, ".sh") {
|
|
||||||
ind = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[ind]), ".appimage") {
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".home", 0777)
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".config", 0777)
|
|
||||||
}
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[ind]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
} else {
|
|
||||||
if len(a.lin) != 0 {
|
|
||||||
var ind int
|
|
||||||
for i, v := range a.lin {
|
|
||||||
if strings.HasSuffix(v, ".sh") {
|
|
||||||
ind = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[ind]), ".appimage") {
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".home", 0777)
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[ind]+".config", 0777)
|
|
||||||
}
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[ind]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.lin[ind]+"\"")
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *app) launchSub(sub int) {
|
|
||||||
if wine {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if !contains(a.lin, a.ex[sub]) {
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[0]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; wine \""+a.ex[sub]+"\"")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[sub]), ".appimage") {
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".home", 0777)
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".config", 0777)
|
|
||||||
}
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[sub]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
} else {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if paDirs && strings.HasSuffix(strings.ToLower(a.ex[sub]), ".appimage") {
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".home", 0777)
|
|
||||||
os.Mkdir(a.dir+"/"+a.ex[sub]+".config", 0777)
|
|
||||||
}
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "export APPNAME="+a.name+";export FILENAME="+a.ex[sub]+";. PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.dir+"\"; \"./"+a.ex[sub]+"\"")
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *app) edit(parent *gtk.Window, reload func()) {
|
|
||||||
tmp := *a
|
|
||||||
parent.SetSensitive(false)
|
|
||||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
||||||
win.Connect("destroy", func() {
|
|
||||||
master = make(map[string][]app)
|
|
||||||
linmaster = make(map[string][]app)
|
|
||||||
cats = make([]string, 0)
|
|
||||||
lin = make([]string, 0)
|
|
||||||
setup()
|
|
||||||
reload()
|
|
||||||
parent.SetSensitive(true)
|
|
||||||
})
|
|
||||||
win.SetDefaultSize(400, 135)
|
|
||||||
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
topLvl.SetMarginStart(10)
|
|
||||||
topLvl.SetMarginEnd(10)
|
|
||||||
topLvl.SetMarginTop(10)
|
|
||||||
topLvl.SetMarginBottom(10)
|
|
||||||
top, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
|
||||||
img, _ := gtk.ImageNewFromPixbuf(a.icon)
|
|
||||||
imgBut, _ := gtk.ButtonNew()
|
|
||||||
imgBut.SetImage(img)
|
|
||||||
imgBut.SetSizeRequest(100, 100)
|
|
||||||
imgBut.Connect("clicked", func() {
|
|
||||||
fil, _ := gtk.FileChooserDialogNewWith1Button("Select Icon", win, gtk.FILE_CHOOSER_ACTION_OPEN, "Open", gtk.RESPONSE_ACCEPT)
|
|
||||||
filter, _ := gtk.FileFilterNew()
|
|
||||||
filter.AddPixbufFormats()
|
|
||||||
filter.SetName("Supported Pictures")
|
|
||||||
fil.AddFilter(filter)
|
|
||||||
but, _ := fil.AddButton("Cancel", gtk.RESPONSE_CANCEL)
|
|
||||||
but.Connect("clicked", func() {
|
|
||||||
fil.Close()
|
|
||||||
})
|
|
||||||
resp := fil.Run()
|
|
||||||
if resp == gtk.RESPONSE_ACCEPT {
|
|
||||||
filename := fil.GetFilename()
|
|
||||||
_, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pix, _ := gdk.PixbufNewFromFileAtSize(filename, 32, 32)
|
|
||||||
tmp.icon = pix
|
|
||||||
img.SetFromPixbuf(pix)
|
|
||||||
fil.Close()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
topRt, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
nameLbl, _ := gtk.LabelNew("Name:")
|
|
||||||
nameLbl.SetHAlign(gtk.ALIGN_START)
|
|
||||||
txtgtbl, _ := gtk.TextTagTableNew()
|
|
||||||
txtBuf, _ := gtk.TextBufferNew(txtgtbl)
|
|
||||||
nameTxt, _ := gtk.TextViewNewWithBuffer(txtBuf)
|
|
||||||
nameTxt.SetAcceptsTab(false)
|
|
||||||
nameTxt.SetWrapMode(gtk.WRAP_CHAR)
|
|
||||||
nameTxt.SetPixelsBelowLines(5)
|
|
||||||
nameTxt.SetHExpand(true)
|
|
||||||
nameTxt.SetVExpand(false)
|
|
||||||
nameTxt.SetBorderWindowSize(gtk.TEXT_WINDOW_BOTTOM, 5)
|
|
||||||
nameShow := tmp.name
|
|
||||||
if tmp.wine {
|
|
||||||
nameShow = strings.TrimSuffix(nameShow, " (Wine)")
|
|
||||||
}
|
|
||||||
txtBuf.SetText(nameShow)
|
|
||||||
vScrollName, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
hScrollName, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
nameScr, _ := gtk.ScrolledWindowNew(hScrollName, vScrollName)
|
|
||||||
nameScr.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
|
|
||||||
nameScr.SetSizeRequest(300, 25)
|
|
||||||
nameScr.SetVExpand(false)
|
|
||||||
nameScr.Add(nameTxt)
|
|
||||||
catLbl, _ := gtk.LabelNew("Category:")
|
|
||||||
catLbl.SetHAlign(gtk.ALIGN_START)
|
|
||||||
catTbl, _ := gtk.TextTagTableNew()
|
|
||||||
catBuf, _ := gtk.TextBufferNew(catTbl)
|
|
||||||
catTxt, _ := gtk.TextViewNewWithBuffer(catBuf)
|
|
||||||
catBuf.SetText(tmp.cat)
|
|
||||||
catTxt.SetAcceptsTab(false)
|
|
||||||
catTxt.SetWrapMode(gtk.WRAP_CHAR)
|
|
||||||
catTxt.SetPixelsBelowLines(5)
|
|
||||||
catTxt.SetHExpand(true)
|
|
||||||
catTxt.SetVExpand(false)
|
|
||||||
catTxt.SetBorderWindowSize(gtk.TEXT_WINDOW_BOTTOM, 5)
|
|
||||||
vScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
hScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
catScr, _ := gtk.ScrolledWindowNew(hScrollCat, vScrollCat)
|
|
||||||
catScr.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
|
|
||||||
catScr.SetSizeRequest(300, 25)
|
|
||||||
catScr.SetVExpand(false)
|
|
||||||
catScr.Add(catTxt)
|
|
||||||
topRt.Add(nameLbl)
|
|
||||||
topRt.Add(nameScr)
|
|
||||||
topRt.Add(catLbl)
|
|
||||||
topRt.Add(catScr)
|
|
||||||
top.Add(imgBut)
|
|
||||||
top.Add(topRt)
|
|
||||||
bot, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
|
||||||
sv, _ := gtk.ButtonNewWithLabel("Save")
|
|
||||||
sv.Connect("clicked", func() {
|
|
||||||
tmp.name, _ = txtBuf.GetText(txtBuf.GetStartIter(), txtBuf.GetEndIter(), true)
|
|
||||||
tmp.cat, _ = catBuf.GetText(catBuf.GetStartIter(), catBuf.GetEndIter(), true)
|
|
||||||
tmp.makeIni()
|
|
||||||
os.Remove(a.dir + "/appicon.png")
|
|
||||||
tmp.icon.SavePNG(a.dir+"/appicon.png", 0)
|
|
||||||
win.Close()
|
|
||||||
})
|
|
||||||
cnl, _ := gtk.ButtonNewWithLabel("Cancel")
|
|
||||||
cnl.Connect("clicked", func() {
|
|
||||||
win.Close()
|
|
||||||
})
|
|
||||||
bot.PackEnd(sv, false, false, 0)
|
|
||||||
bot.PackEnd(cnl, false, false, 0)
|
|
||||||
topLvl.Add(top)
|
|
||||||
topLvl.Add(bot)
|
|
||||||
win.Add(topLvl)
|
|
||||||
win.ShowAll()
|
|
||||||
win.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *app) makeIni() {
|
|
||||||
os.Remove(a.dir + "/appinfo.ini")
|
|
||||||
fil, err := os.Create(a.dir + "/appinfo.ini")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ini := "[General]\n"
|
|
||||||
ini += "Category=" + a.cat + "\n"
|
|
||||||
ini += "Name=" + a.name + "\n"
|
|
||||||
wrt := bufio.NewWriter(fil)
|
|
||||||
wrt.WriteString(ini)
|
|
||||||
wrt.Flush()
|
|
||||||
}
|
|
||||||
@@ -1,26 +1,11 @@
|
|||||||
module github.com/CalebQ42/LinuxPA
|
module github.com/CalebQ42/LinuxPA
|
||||||
|
|
||||||
go 1.17
|
go 1.23.1
|
||||||
|
|
||||||
|
require github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/CalebQ42/GoAppImage v0.4.0
|
github.com/ebitengine/purego v0.8.2 // indirect
|
||||||
github.com/gotk3/gotk3 v0.6.1
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
golang.org/x/sys v0.29.0 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/adrg/xdg v0.2.2 // indirect
|
|
||||||
github.com/andybalholm/brotli v1.0.1 // indirect
|
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
|
||||||
github.com/golang/snappy v0.0.2 // indirect
|
|
||||||
github.com/klauspost/compress v1.11.4 // indirect
|
|
||||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
|
||||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
|
||||||
github.com/pierrec/lz4/v4 v4.1.2 // indirect
|
|
||||||
github.com/ulikunitz/xz v0.5.9 // indirect
|
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
|
||||||
go.lsp.dev/uri v0.3.0 // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 // indirect
|
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,70 +1,8 @@
|
|||||||
github.com/CalebQ42/GoAppImage v0.4.0 h1:aF+Y/vyo/RGhoyZEW1CMY6WyRWrZZO4ydsRFAtIGnaY=
|
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
|
||||||
github.com/CalebQ42/GoAppImage v0.4.0/go.mod h1:qHudJKAn/dlkNWNnH4h1YKXp29EZ7Bppsn7sNP2HuvU=
|
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
github.com/adrg/xdg v0.2.2 h1:A7ZHKRz5KGOLJX/bg7IPzStryhvCzAE1wX+KWawPiAo=
|
github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b h1:JJfspevP3YOXcSKVABizYOv++yMpTJIdPUtoDzF/RWw=
|
||||||
github.com/adrg/xdg v0.2.2/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
|
github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q=
|
||||||
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
||||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
|
||||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
|
||||||
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
|
|
||||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
|
||||||
github.com/gotk3/gotk3 v0.6.1 h1:GJ400a0ecEEWrzjBvzBzH+pB/esEMIGdB9zPSmBdoeo=
|
|
||||||
github.com/gotk3/gotk3 v0.6.1/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
|
||||||
github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU=
|
|
||||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
|
||||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
|
||||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
|
||||||
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/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
|
||||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
|
||||||
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
|
|
||||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
|
||||||
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
|
|
||||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
|
||||||
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
|
|
||||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
|
||||||
go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo=
|
|
||||||
go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 h1:X/2sJAybVknnUnV7AD2HdT6rm2p5BP6eH2j+igduWgk=
|
|
||||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
|
||||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
|
|||||||
@@ -0,0 +1,260 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A rectangle with borders.
|
||||||
|
// Default only has black borders.
|
||||||
|
type Rect struct {
|
||||||
|
x int32
|
||||||
|
y int32
|
||||||
|
h int32
|
||||||
|
w int32
|
||||||
|
radius int32
|
||||||
|
reload bool
|
||||||
|
shown bool
|
||||||
|
rendering bool
|
||||||
|
|
||||||
|
borderWidth int32
|
||||||
|
borderColor color.RGBA
|
||||||
|
fillColor color.RGBA
|
||||||
|
|
||||||
|
curTweens map[string]*Tween
|
||||||
|
tex rl.RenderTexture2D
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRect(x, y, height, width int32) *Rect {
|
||||||
|
r := &Rect{
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
h: height,
|
||||||
|
w: width,
|
||||||
|
radius: 0,
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: rl.Black,
|
||||||
|
fillColor: rl.Blank,
|
||||||
|
reload: true,
|
||||||
|
curTweens: make(map[string]*Tween),
|
||||||
|
}
|
||||||
|
r.tex = rl.LoadRenderTexture(width, height)
|
||||||
|
rl.SetTextureFilter(r.tex.Texture, rl.FilterAnisotropic8x|rl.FilterBilinear)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) Copy() *Rect {
|
||||||
|
return &Rect{
|
||||||
|
x: r.x,
|
||||||
|
y: r.y,
|
||||||
|
h: r.h,
|
||||||
|
w: r.w,
|
||||||
|
radius: r.radius,
|
||||||
|
borderWidth: r.borderWidth,
|
||||||
|
borderColor: r.borderColor,
|
||||||
|
fillColor: r.fillColor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) addTween(key string, old, new int32) {
|
||||||
|
r.curTweens[key] = NewTween(old, new, 1000*time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) SetPosition(x, y int32) {
|
||||||
|
if !r.shown {
|
||||||
|
r.x, r.y = x, y
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.x != x {
|
||||||
|
r.addTween("x", r.x, x)
|
||||||
|
}
|
||||||
|
if r.y != y {
|
||||||
|
r.addTween("y", r.y, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) SetSize(h, w int32) {
|
||||||
|
if !r.shown {
|
||||||
|
r.h, r.w = h, w
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.h != h {
|
||||||
|
r.addTween("h", r.h, h)
|
||||||
|
r.reload = true
|
||||||
|
}
|
||||||
|
if r.w != w {
|
||||||
|
r.addTween("w", r.w, w)
|
||||||
|
r.reload = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) SetBorderRadius(radius int32) {
|
||||||
|
if !r.shown {
|
||||||
|
r.radius = radius
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.radius != radius {
|
||||||
|
r.addTween("radius", r.radius, radius)
|
||||||
|
r.reload = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) SetBorderWidth(w int32) {
|
||||||
|
if !r.shown {
|
||||||
|
r.borderWidth = w
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.borderWidth != w {
|
||||||
|
r.addTween("borderWidth", r.borderWidth, w)
|
||||||
|
r.reload = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) SetBorderColor(c color.RGBA) {
|
||||||
|
if r.borderColor != c {
|
||||||
|
r.reload = true
|
||||||
|
}
|
||||||
|
r.borderColor = c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) SetFillColor(c color.RGBA) {
|
||||||
|
if r.fillColor != c {
|
||||||
|
r.reload = true
|
||||||
|
}
|
||||||
|
r.fillColor = c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) Draw() {
|
||||||
|
r.shown = true
|
||||||
|
if !r.reload && len(r.curTweens) == 0 {
|
||||||
|
rl.DrawTextureEx(r.tex.Texture, rl.NewVector2(float32(r.x), float32(r.y)), 0, 1, rl.White)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var curRect *Rect
|
||||||
|
updateTex := false
|
||||||
|
if len(r.curTweens) != 0 {
|
||||||
|
curRect = r.Copy()
|
||||||
|
tween, ok := r.curTweens["x"]
|
||||||
|
if ok {
|
||||||
|
curRect.x = tween.CurVal()
|
||||||
|
if tween.Ended() {
|
||||||
|
r.x = curRect.x
|
||||||
|
delete(r.curTweens, "x")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tween, ok = r.curTweens["y"]
|
||||||
|
if ok {
|
||||||
|
curRect.y = tween.CurVal()
|
||||||
|
if tween.Ended() {
|
||||||
|
r.y = curRect.y
|
||||||
|
delete(r.curTweens, "y")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tween, ok = r.curTweens["h"]
|
||||||
|
if ok {
|
||||||
|
curRect.h = tween.CurVal()
|
||||||
|
if curRect.h != r.h {
|
||||||
|
updateTex = true
|
||||||
|
}
|
||||||
|
if tween.Ended() {
|
||||||
|
r.h = curRect.h
|
||||||
|
delete(r.curTweens, "h")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tween, ok = r.curTweens["w"]
|
||||||
|
if ok {
|
||||||
|
curRect.w = tween.CurVal()
|
||||||
|
if curRect.w != r.w {
|
||||||
|
updateTex = true
|
||||||
|
}
|
||||||
|
if tween.Ended() {
|
||||||
|
r.w = curRect.w
|
||||||
|
delete(r.curTweens, "w")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tween, ok = r.curTweens["radius"]
|
||||||
|
if ok {
|
||||||
|
curRect.radius = tween.CurVal()
|
||||||
|
if curRect.radius != r.radius {
|
||||||
|
updateTex = true
|
||||||
|
}
|
||||||
|
if tween.Ended() {
|
||||||
|
r.radius = curRect.radius
|
||||||
|
delete(r.curTweens, "radius")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tween, ok = r.curTweens["borderWidth"]
|
||||||
|
if ok {
|
||||||
|
curRect.borderWidth = tween.CurVal()
|
||||||
|
if curRect.borderWidth != r.borderWidth {
|
||||||
|
updateTex = true
|
||||||
|
}
|
||||||
|
if tween.Ended() {
|
||||||
|
r.borderWidth = curRect.borderWidth
|
||||||
|
delete(r.curTweens, "borderWidth")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
curRect = r
|
||||||
|
}
|
||||||
|
if r.reload || updateTex {
|
||||||
|
// rl.UnloadTexture(r.tex)
|
||||||
|
// r.tex = rl.LoadTextureFromImage(curRect.buildImage())
|
||||||
|
// rl.UpdateTexture(r.tex, rl.LoadImageColors(curRect.buildImage()))
|
||||||
|
rl.BeginTextureMode(r.tex)
|
||||||
|
curRect.drawTexture()
|
||||||
|
rl.EndTextureMode()
|
||||||
|
}
|
||||||
|
rl.DrawTexturePro(r.tex.Texture, rl.NewRectangle(0, 0, float32(curRect.w), float32(curRect.h)), rl.NewRectangle(float32(curRect.x), float32(curRect.y), float32(curRect.w), float32(curRect.h)), rl.NewVector2(0, 0), 0, rl.White)
|
||||||
|
// rl.DrawTextureEx(r.tex.Texture, rl.NewVector2(float32(curRect.x), float32(curRect.y)), 0, 1, rl.White)
|
||||||
|
r.reload = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Rect) drawTexture() {
|
||||||
|
rl.ClearBackground(rl.Blank)
|
||||||
|
// Filled areas
|
||||||
|
if r.fillColor != rl.Blank {
|
||||||
|
rl.DrawRectangle(r.radius, 0, (r.w - (2 * r.radius)), r.h, r.fillColor)
|
||||||
|
if r.radius > 0 {
|
||||||
|
rl.DrawRectangle((r.w - r.radius), r.radius, r.radius, (r.h - (2 * r.radius)), r.fillColor)
|
||||||
|
rl.DrawRectangle(0, r.radius, r.radius, (r.h - (2 * r.radius)), r.fillColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.borderColor != rl.Blank {
|
||||||
|
// Horizontal lines
|
||||||
|
rl.DrawRectangle(r.radius, 0, (r.w - (2 * r.radius)), r.borderWidth, r.borderColor)
|
||||||
|
rl.DrawRectangle(r.radius, (r.h)-(r.borderWidth), (r.w - (2 * r.radius)), r.borderWidth, r.borderColor)
|
||||||
|
// Vertical lines
|
||||||
|
rl.DrawRectangle(0, r.radius, r.borderWidth, (r.h - (2 * r.radius)), r.borderColor)
|
||||||
|
rl.DrawRectangle((r.w)-(r.borderWidth), r.radius, r.borderWidth, (r.h - (2 * r.radius)), r.borderColor)
|
||||||
|
}
|
||||||
|
if r.radius > 0 {
|
||||||
|
r.placeCorners()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Rect) placeCorners() {
|
||||||
|
//bl
|
||||||
|
if r.borderWidth > 0 {
|
||||||
|
rl.DrawRing(rl.NewVector2(float32(r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 180, 270, 20, r.borderColor)
|
||||||
|
}
|
||||||
|
rl.DrawCircleSector(rl.NewVector2(float32(r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), 180, 270, 20, r.fillColor)
|
||||||
|
//tl
|
||||||
|
if r.borderWidth > 0 {
|
||||||
|
rl.DrawRing(rl.NewVector2(float32(r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 90, 180, 20, r.borderColor)
|
||||||
|
}
|
||||||
|
rl.DrawCircleSector(rl.NewVector2(float32(r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), 90, 180, 20, r.fillColor)
|
||||||
|
//tr
|
||||||
|
if r.borderWidth > 0 {
|
||||||
|
rl.DrawRing(rl.NewVector2(float32(r.w-r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 0, 90, 20, r.borderColor)
|
||||||
|
}
|
||||||
|
rl.DrawCircleSector(rl.NewVector2(float32(r.w-r.radius), float32(r.h-r.radius)), float32(r.radius-r.borderWidth), 0, 90, 20, r.fillColor)
|
||||||
|
//br
|
||||||
|
if r.borderWidth > 0 {
|
||||||
|
rl.DrawRing(rl.NewVector2(float32(r.w-r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), float32(r.radius), 270, 360, 20, r.borderColor)
|
||||||
|
}
|
||||||
|
rl.DrawCircleSector(rl.NewVector2(float32(r.w-r.radius), float32(r.radius)), float32(r.radius-r.borderWidth), 270, 360, 20, r.fillColor)
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Window struct{}
|
||||||
|
|
||||||
|
func Test() {
|
||||||
|
rl.SetConfigFlags(rl.FlagWindowResizable | rl.FlagWindowHighdpi | rl.FlagVsyncHint | rl.FlagMsaa4xHint)
|
||||||
|
rl.InitWindow(800, 450, "raylib [core] example - basic window")
|
||||||
|
defer rl.CloseWindow()
|
||||||
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
|
noto := rl.LoadFont("./noto-sans.ttf")
|
||||||
|
txtImg := rl.ImageTextEx(noto, "Hello World!", 50, 0, rl.Black)
|
||||||
|
txt := rl.LoadTextureFromImage(txtImg)
|
||||||
|
|
||||||
|
tmpRect := NewRect(10, 10, 250, 500)
|
||||||
|
tmpRect.SetBorderRadius(25)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
// tmpRect.SetBorderRadius(0)
|
||||||
|
// tmpRect.SetPosition(100, 100)
|
||||||
|
tmpRect.SetSize(400, 700)
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
// tmpRect.SetBorderRadius(25)
|
||||||
|
// tmpRect.SetPosition(10, 10)
|
||||||
|
tmpRect.SetSize(250, 500)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// tmpRect.SetFillColor(rl.Green)
|
||||||
|
for !rl.WindowShouldClose() {
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.DrawFPS(0, 0)
|
||||||
|
|
||||||
|
rl.ClearBackground(rl.DarkGray)
|
||||||
|
// rl.DrawText("Congrats! You created your first window!", 190, 100, 20, rl.LightGray)
|
||||||
|
// // rl.DrawTextEx(noto, "Congrats! You created your first window!", rl.NewVector2(190, 200), 48, 0, rl.Black)
|
||||||
|
tmpRect.Draw()
|
||||||
|
rl.DrawTexture(txt, 50, 50, rl.Black)
|
||||||
|
rl.EndDrawing()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tween struct {
|
||||||
|
startVal int32
|
||||||
|
startTime time.Time
|
||||||
|
dif int32
|
||||||
|
dur time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTween(startVal, endVal int32, duration time.Duration) *Tween {
|
||||||
|
return &Tween{
|
||||||
|
startVal: startVal,
|
||||||
|
dif: endVal - startVal,
|
||||||
|
dur: duration,
|
||||||
|
startTime: time.Now().Round(time.Millisecond),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tween) CurVal() int32 {
|
||||||
|
since := time.Now().Round(time.Millisecond).Sub(t.startTime)
|
||||||
|
if since <= 0 {
|
||||||
|
return t.startVal
|
||||||
|
}
|
||||||
|
if since >= t.dur {
|
||||||
|
return t.startVal + t.dif
|
||||||
|
}
|
||||||
|
m := float32(since.Milliseconds()) / float32(t.dur.Milliseconds())
|
||||||
|
m = -1 * float32(math.Log10(-.9*float64(m)+1))
|
||||||
|
return t.startVal + int32(math.Round(float64(float32(t.dif)*m)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tween) Ended() bool {
|
||||||
|
return time.Now().Round(time.Millisecond).Sub(t.startTime) >= t.dur
|
||||||
|
}
|
||||||
@@ -1,61 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/CalebQ42/LinuxPA/internal/ui"
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/gtk"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
version = "2.2.0.0"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
master map[string][]app
|
|
||||||
linmaster map[string][]app
|
|
||||||
cats []string
|
|
||||||
lin []string
|
|
||||||
comEnbld bool
|
|
||||||
populated bool
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
forced := flag.Bool("force-update", false, "Force the update dialog to be shown")
|
ui.Test()
|
||||||
flag.Parse()
|
|
||||||
os.MkdirAll("PortableApps/LinuxPACom", 0777)
|
|
||||||
master = make(map[string][]app)
|
|
||||||
linmaster = make(map[string][]app)
|
|
||||||
uiStart(*forced)
|
|
||||||
}
|
|
||||||
|
|
||||||
func uiStart(forced bool) {
|
|
||||||
gtk.Init(nil)
|
|
||||||
setup()
|
|
||||||
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Window not created", err)
|
|
||||||
}
|
|
||||||
win.SetTitle("LinuxPA")
|
|
||||||
win.Connect("destroy", func() {
|
|
||||||
savePrefs()
|
|
||||||
gtk.MainQuit()
|
|
||||||
})
|
|
||||||
win.SetDefaultSize(500, 500)
|
|
||||||
win.SetPosition(gtk.WIN_POS_CENTER)
|
|
||||||
ui(win)
|
|
||||||
win.ShowAll()
|
|
||||||
win.Show()
|
|
||||||
update(win, forced)
|
|
||||||
gtk.Main()
|
|
||||||
}
|
|
||||||
|
|
||||||
func contains(arr []string, str string) bool {
|
|
||||||
for _, v := range arr {
|
|
||||||
if v == str {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -1,72 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/gob"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
wine bool
|
|
||||||
wineAvail bool
|
|
||||||
portableHide bool
|
|
||||||
betaUpdate bool
|
|
||||||
versionNewest = true
|
|
||||||
paDirs = true
|
|
||||||
)
|
|
||||||
|
|
||||||
func savePrefs() {
|
|
||||||
os.Remove("PortableApps/LinuxPACom/Prefs.gob")
|
|
||||||
fil, err := os.Create("PortableApps/LinuxPACom/Prefs.gob")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
enc := gob.NewEncoder(fil)
|
|
||||||
err = enc.Encode(wine)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = enc.Encode(portableHide)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = enc.Encode(versionNewest)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = enc.Encode(paDirs)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = enc.Encode(betaUpdate)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadPrefs() {
|
|
||||||
fil, err := os.Open("PortableApps/LinuxPACom/Prefs.gob")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dec := gob.NewDecoder(fil)
|
|
||||||
err = dec.Decode(&wine)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = dec.Decode(&portableHide)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = dec.Decode(&versionNewest)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = dec.Decode(&paDirs)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = dec.Decode(&betaUpdate)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-206
@@ -1,206 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/glib"
|
|
||||||
"github.com/gotk3/gotk3/gtk"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
commonHelp = "The common.sh is run before every app is launched and allows you to set variables such as $HOME. For directories, ALWAYS start the directory with $PWD which points to the directory where LinuxPA is. To allow for greater customization and isolation, you can use the $FILENAME variable which is the filename of the executable you're using and the $APPNAME variable which is the name of the app being lanched."
|
|
||||||
)
|
|
||||||
|
|
||||||
func settingsUI(parent *gtk.Window, onExit func()) {
|
|
||||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
||||||
win.SetTransientFor(parent)
|
|
||||||
parent.SetSensitive(false)
|
|
||||||
win.SetDefaultSize(600, 300)
|
|
||||||
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
|
||||||
win.Connect("destroy", func() {
|
|
||||||
savePrefs()
|
|
||||||
parent.SetSensitive(true)
|
|
||||||
onExit()
|
|
||||||
})
|
|
||||||
comTagTbl, _ := gtk.TextTagTableNew()
|
|
||||||
comBuf, _ := gtk.TextBufferNew(comTagTbl)
|
|
||||||
ntbk, _ := gtk.NotebookNew()
|
|
||||||
gnrl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
gnrl.SetMarginStart(10)
|
|
||||||
gnrl.SetMarginEnd(10)
|
|
||||||
gnrl.SetMarginTop(10)
|
|
||||||
gnrl.SetMarginBottom(10)
|
|
||||||
dlWine, _ := gtk.ButtonNewWithLabel("Download Wine")
|
|
||||||
wineCheck, _ := gtk.CheckButtonNewWithLabel("Show Windows apps (Wine)")
|
|
||||||
wineLbl, _ := gtk.LabelNew("PortableApps/LinuxPACom/Wine present")
|
|
||||||
dlWine.Connect("clicked", func() {
|
|
||||||
cb := make(chan bool)
|
|
||||||
downloadWine(win, cb)
|
|
||||||
go func() {
|
|
||||||
v := <-cb
|
|
||||||
if v {
|
|
||||||
setupTxt(comBuf)
|
|
||||||
wineLbl.Show()
|
|
||||||
}
|
|
||||||
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); os.IsNotExist(err) {
|
|
||||||
if _, errd := exec.LookPath("wine"); errd == nil {
|
|
||||||
wineAvail = true
|
|
||||||
}
|
|
||||||
} else if err == nil {
|
|
||||||
wineAvail = true
|
|
||||||
}
|
|
||||||
glib.IdleAdd(func() {
|
|
||||||
if !wineAvail {
|
|
||||||
wineCheck.SetSensitive(false)
|
|
||||||
wineCheck.SetTooltipText("Download wine to run windows apps")
|
|
||||||
} else {
|
|
||||||
wineCheck.SetSensitive(true)
|
|
||||||
wineCheck.SetTooltipText("")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
if !comEnbld {
|
|
||||||
dlWine.SetSensitive(false)
|
|
||||||
dlWine.SetTooltipText("common.sh needed")
|
|
||||||
}
|
|
||||||
pthdCheck, _ := gtk.CheckButtonNewWithLabel("Hide \"Portable\" from app name")
|
|
||||||
pthdCheck.Connect("toggled", func() {
|
|
||||||
portableHide = pthdCheck.GetActive()
|
|
||||||
master = make(map[string][]app)
|
|
||||||
linmaster = make(map[string][]app)
|
|
||||||
cats = make([]string, 0)
|
|
||||||
lin = make([]string, 0)
|
|
||||||
setup()
|
|
||||||
})
|
|
||||||
pthdCheck.SetActive(portableHide)
|
|
||||||
if !wineAvail {
|
|
||||||
wineCheck.SetSensitive(false)
|
|
||||||
wineCheck.SetTooltipText("Download wine to run windows apps")
|
|
||||||
}
|
|
||||||
wineCheck.SetActive(wine)
|
|
||||||
wineCheck.Connect("toggled", func() {
|
|
||||||
wine = wineCheck.GetActive()
|
|
||||||
})
|
|
||||||
versCheck, _ := gtk.CheckButtonNewWithLabel("Only show newest app version in downloads (A bit iffy ATM)")
|
|
||||||
versCheck.SetActive(versionNewest)
|
|
||||||
versCheck.Connect("toggled", func() {
|
|
||||||
versionNewest = versCheck.GetActive()
|
|
||||||
})
|
|
||||||
paDirsCheck, _ := gtk.CheckButtonNewWithLabel("Create .home and .config directories for AppImages")
|
|
||||||
paDirsCheck.SetActive(paDirs)
|
|
||||||
paDirsCheck.Connect("toggled", func() {
|
|
||||||
paDirs = paDirsCheck.GetActive()
|
|
||||||
})
|
|
||||||
betaCheck, _ := gtk.CheckButtonNewWithLabel("Update to beta releases")
|
|
||||||
gnrl.Add(wineLbl)
|
|
||||||
gnrl.Add(dlWine)
|
|
||||||
gnrl.Add(pthdCheck)
|
|
||||||
gnrl.Add(wineCheck)
|
|
||||||
gnrl.Add(versCheck)
|
|
||||||
gnrl.Add(paDirsCheck)
|
|
||||||
gnrl.Add(betaCheck)
|
|
||||||
ntbk.AppendPage(gnrl, getLabel("General"))
|
|
||||||
com, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
com.SetMarginStart(10)
|
|
||||||
com.SetMarginEnd(10)
|
|
||||||
com.SetMarginTop(10)
|
|
||||||
com.SetMarginBottom(10)
|
|
||||||
comEdit, _ := gtk.TextViewNewWithBuffer(comBuf)
|
|
||||||
comEdit.SetVExpand(true)
|
|
||||||
comEdit.SetHExpand(true)
|
|
||||||
vScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
hScroll, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
comScrl, _ := gtk.ScrolledWindowNew(hScroll, vScroll)
|
|
||||||
comScrl.Add(comEdit)
|
|
||||||
svBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
|
||||||
sv, _ := gtk.ButtonNewWithLabel("Save")
|
|
||||||
sv.Connect("clicked", func() {
|
|
||||||
beg, end := comBuf.GetBounds()
|
|
||||||
txt, _ := comBuf.GetText(beg, end, true)
|
|
||||||
ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", []byte(txt), 0777)
|
|
||||||
})
|
|
||||||
cnl, _ := gtk.ButtonNewWithLabel("Cancel")
|
|
||||||
cnl.Connect("clicked", func() {
|
|
||||||
setupTxt(comBuf)
|
|
||||||
})
|
|
||||||
info, _ := gtk.ButtonNewWithLabel("Info")
|
|
||||||
info.Connect("clicked", func() {
|
|
||||||
infoBox, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
||||||
infoBox.SetTransientFor(parent)
|
|
||||||
infoBox.SetDefaultSize(300, 80)
|
|
||||||
infoBox.SetName("common.sh info")
|
|
||||||
infoBox.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
|
||||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
infolbl, _ := gtk.LabelNew(commonHelp)
|
|
||||||
infolbl.SetLineWrap(true)
|
|
||||||
infolbl.SetSizeRequest(200, 50)
|
|
||||||
box.Add(infolbl)
|
|
||||||
infoBox.Add(box)
|
|
||||||
infoBox.ShowAll()
|
|
||||||
infoBox.Show()
|
|
||||||
})
|
|
||||||
svBox.Add(sv)
|
|
||||||
svBox.Add(cnl)
|
|
||||||
svBox.Add(info)
|
|
||||||
com.Add(comScrl)
|
|
||||||
com.Add(svBox)
|
|
||||||
ntbk.AppendPage(com, getLabel("common.sh"))
|
|
||||||
win.Add(ntbk)
|
|
||||||
win.ShowAll()
|
|
||||||
if !comEnbld {
|
|
||||||
comScrl.Hide()
|
|
||||||
svBox.Hide()
|
|
||||||
mkCom, _ := gtk.ButtonNewWithLabel("Create common.sh")
|
|
||||||
mkCom.Connect("clicked", func() {
|
|
||||||
err := ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", []byte("export HOME=$PWD/PortableApps/LinuxPACom/Home"), 0777)
|
|
||||||
if err == nil {
|
|
||||||
mkCom.Hide()
|
|
||||||
comScrl.Show()
|
|
||||||
svBox.Show()
|
|
||||||
setupTxt(comBuf)
|
|
||||||
comEnbld = true
|
|
||||||
dlWine.SetSensitive(true)
|
|
||||||
dlWine.SetTooltipText("")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
in, _ := gtk.ButtonNewWithLabel("Info")
|
|
||||||
in.Connect("clicked", func() {
|
|
||||||
infoBox, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
||||||
infoBox.SetTransientFor(parent)
|
|
||||||
infoBox.SetDefaultSize(300, 80)
|
|
||||||
infoBox.SetName("common.sh info")
|
|
||||||
infoBox.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
|
||||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
infolbl, _ := gtk.LabelNew(commonHelp)
|
|
||||||
infolbl.SetLineWrap(true)
|
|
||||||
infolbl.SetSizeRequest(200, 50)
|
|
||||||
box.Add(infolbl)
|
|
||||||
infoBox.Add(box)
|
|
||||||
infoBox.ShowAll()
|
|
||||||
infoBox.Show()
|
|
||||||
})
|
|
||||||
mkCom.Show()
|
|
||||||
com.Add(mkCom)
|
|
||||||
com.Add(in)
|
|
||||||
} else {
|
|
||||||
setupTxt(comBuf)
|
|
||||||
}
|
|
||||||
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); err != nil && os.IsNotExist(err) {
|
|
||||||
wineLbl.Hide()
|
|
||||||
}
|
|
||||||
win.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupTxt(buf *gtk.TextBuffer) {
|
|
||||||
fil, _ := os.Open("PortableApps/LinuxPACom/common.sh")
|
|
||||||
btys, _ := ioutil.ReadAll(fil)
|
|
||||||
buf.SetText(string(btys))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLabel(name string) *gtk.Label {
|
|
||||||
lbl, _ := gtk.LabelNew(name)
|
|
||||||
return lbl
|
|
||||||
}
|
|
||||||
@@ -1,294 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
_ "image/png"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
goappimage "github.com/CalebQ42/GoAppImage"
|
|
||||||
"github.com/gotk3/gotk3/gdk"
|
|
||||||
"github.com/gotk3/gotk3/gtk"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setup() {
|
|
||||||
loadPrefs()
|
|
||||||
if _, err := os.Open("PortableApps/LinuxPACom/Wine"); os.IsNotExist(err) {
|
|
||||||
if _, errd := exec.LookPath("wine"); errd == nil {
|
|
||||||
wineAvail = true
|
|
||||||
}
|
|
||||||
} else if err == nil {
|
|
||||||
wineAvail = true
|
|
||||||
}
|
|
||||||
if !wineAvail {
|
|
||||||
wine = false
|
|
||||||
}
|
|
||||||
PortableAppsFold, err := os.Open("PortableApps")
|
|
||||||
if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() {
|
|
||||||
os.Mkdir("PortableApps", 0777)
|
|
||||||
PortableAppsFold, err = os.Open("PortableApps")
|
|
||||||
if err != nil {
|
|
||||||
panic("Can't find PortableApps folder and can't create one!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err = os.Open("PortableApps/LinuxPACom"); err != nil {
|
|
||||||
os.Mkdir("PortableApps/LinuxPACom", 0777)
|
|
||||||
}
|
|
||||||
_, err = os.Open("PortableApps/LinuxPACom/common.sh")
|
|
||||||
if err == nil {
|
|
||||||
comEnbld = true
|
|
||||||
}
|
|
||||||
PAFolds, _ := PortableAppsFold.Readdirnames(-1)
|
|
||||||
sort.Strings(PAFolds)
|
|
||||||
for _, v := range PAFolds {
|
|
||||||
fold, _ := os.Open("PortableApps/" + v)
|
|
||||||
if stat, _ := fold.Stat(); stat.IsDir() && stat.Name() != "PortableApps.com" && stat.Name() != "LinuxPACom" {
|
|
||||||
ap := processApp("PortableApps/" + v)
|
|
||||||
if !reflect.DeepEqual(ap, app{}) {
|
|
||||||
if _, ok := master[ap.cat]; !ok {
|
|
||||||
cats = append(cats, ap.cat)
|
|
||||||
sort.Strings(cats)
|
|
||||||
}
|
|
||||||
if len(ap.lin) != 0 {
|
|
||||||
if _, ok := linmaster[ap.cat]; !ok {
|
|
||||||
lin = append(lin, ap.cat)
|
|
||||||
sort.Strings(lin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
master[ap.cat] = append(master[ap.cat], ap)
|
|
||||||
if len(ap.lin) != 0 {
|
|
||||||
linmaster[ap.cat] = append(linmaster[ap.cat], ap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
populated = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func processApp(fold string) (out app) {
|
|
||||||
wd, _ := os.Getwd()
|
|
||||||
out.dir = wd + "/" + fold
|
|
||||||
folder, _ := os.Open(fold)
|
|
||||||
fis, _ := folder.Readdirnames(-1)
|
|
||||||
for _, v := range fis {
|
|
||||||
tmp, _ := os.Open(fold + "/" + v)
|
|
||||||
stat, _ := tmp.Stat()
|
|
||||||
if stat.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
//TODO: check permission to see if it has exec permission
|
|
||||||
if strings.HasSuffix(strings.ToLower(v), ".appimage") {
|
|
||||||
out.appimg = append(out.appimg, v)
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
out.lin = append(out.lin, v)
|
|
||||||
} else if strings.HasSuffix(strings.ToLower(v), ".exe") {
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
} else {
|
|
||||||
btys := make([]byte, 4)
|
|
||||||
rdr := bufio.NewReader(tmp)
|
|
||||||
rdr.Read(btys)
|
|
||||||
if (strings.Contains(strings.ToLower(string(btys)), "elf") && !strings.HasSuffix(strings.ToLower(v), ".so") && !strings.Contains(v, ".so.")) || strings.HasPrefix(strings.ToLower(string(btys)), "#!") {
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
out.lin = append(out.lin, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(out.ex) == 0 {
|
|
||||||
return app{}
|
|
||||||
}
|
|
||||||
if len(out.lin) == 0 {
|
|
||||||
out.name += " (Wine)"
|
|
||||||
out.wine = true
|
|
||||||
}
|
|
||||||
out.icon = getIcon(fold)
|
|
||||||
out.ini = findInfo(fold)
|
|
||||||
if out.ini != nil {
|
|
||||||
out.name = getName(out.ini)
|
|
||||||
out.cat = getCat(out.ini)
|
|
||||||
}
|
|
||||||
if len(out.appimg) > 0 && out.name == "" && out.cat == "" && out.icon == nil {
|
|
||||||
os.Mkdir(out.dir+"/.appimageconfig", 0777)
|
|
||||||
ai := goappimage.NewAppImage(out.dir + "/" + out.appimg[0])
|
|
||||||
fil, err := os.Open(out.dir + "/.appimageconfig/the.md5")
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
ai.ExtractFile("*.desktop", out.dir+"/.appimageconfig/", false)
|
|
||||||
appimageconfig, _ := os.Open(out.dir + "/.appimageconfig")
|
|
||||||
appdirs, _ := appimageconfig.Readdirnames(-1)
|
|
||||||
for _, dirs := range appdirs {
|
|
||||||
desktopFil, _ := os.Open(out.dir + "/.appimageconfig/" + dirs)
|
|
||||||
if stat, _ := desktopFil.Stat(); strings.HasSuffix(dirs, ".desktop") && !stat.IsDir() {
|
|
||||||
os.Rename(out.dir+"/.appimageconfig/"+dirs, out.dir+"/.appimageconfig/the.desktop")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desk, _ := os.Open(out.dir + "/.appimageconfig/the.desktop")
|
|
||||||
name, cat, icon := extractDesktopInfo(desk)
|
|
||||||
if out.name == "" {
|
|
||||||
out.name = name
|
|
||||||
}
|
|
||||||
if out.cat == "" {
|
|
||||||
out.cat = cat
|
|
||||||
}
|
|
||||||
if out.icon == nil {
|
|
||||||
it, _ := gtk.IconThemeGetDefault()
|
|
||||||
out.icon, err = it.LoadIcon(icon, 64, gtk.ICON_LOOKUP_GENERIC_FALLBACK)
|
|
||||||
}
|
|
||||||
fil, _ = os.Create(out.dir + "/.appimageconfig/the.md5")
|
|
||||||
wrtr := bufio.NewWriter(fil)
|
|
||||||
wrtr.WriteString(ai.Md5)
|
|
||||||
wrtr.Flush()
|
|
||||||
} else {
|
|
||||||
rdr := bufio.NewReader(fil)
|
|
||||||
filMd, _, _ := rdr.ReadLine()
|
|
||||||
oldMd := string(filMd)
|
|
||||||
if oldMd != ai.Md5 {
|
|
||||||
ai.ExtractFile("*.desktop", out.dir+"/.appimageconfig/", false)
|
|
||||||
appimageconfig, _ := os.Open(out.dir + "/.appimageconfig")
|
|
||||||
appdirs, _ := appimageconfig.Readdirnames(-1)
|
|
||||||
for _, dirs := range appdirs {
|
|
||||||
desktopFil, _ := os.Open(out.dir + "/.appimageconfig/" + dirs)
|
|
||||||
if stat, _ := desktopFil.Stat(); strings.HasSuffix(dirs, ".desktop") && !stat.IsDir() {
|
|
||||||
os.Rename(out.dir+"/.appimageconfig/"+dirs, out.dir+"/.appimageconfig/the.desktop")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
os.Remove(out.dir + "/.appimageconfig/the.md5")
|
|
||||||
fil, _ = os.Create(out.dir + "/.appimageconfig/the.md5")
|
|
||||||
wrtr := bufio.NewWriter(fil)
|
|
||||||
wrtr.WriteString(ai.Md5)
|
|
||||||
wrtr.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desk, _ := os.Open(out.dir + "/.appimageconfig/the.desktop")
|
|
||||||
name, cat, icon := extractDesktopInfo(desk)
|
|
||||||
if out.name == "" {
|
|
||||||
out.name = name
|
|
||||||
}
|
|
||||||
if out.cat == "" {
|
|
||||||
out.cat = cat
|
|
||||||
}
|
|
||||||
if out.icon == nil {
|
|
||||||
it, _ := gtk.IconThemeGetDefault()
|
|
||||||
out.icon, err = it.LoadIcon(icon, 32, gtk.ICON_LOOKUP_GENERIC_FALLBACK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if out.name == "" {
|
|
||||||
out.name = strings.TrimPrefix(fold, "PortableApps/")
|
|
||||||
}
|
|
||||||
if out.cat == "" {
|
|
||||||
out.cat = "Other"
|
|
||||||
}
|
|
||||||
if portableHide {
|
|
||||||
out.name = strings.TrimSuffix(out.name, "Portable")
|
|
||||||
}
|
|
||||||
out.name = strings.TrimSpace(out.name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCat(ini *os.File) string {
|
|
||||||
rdr := bufio.NewReader(ini)
|
|
||||||
var ret string
|
|
||||||
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
|
||||||
if strings.HasPrefix(string(line), "Category=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "Category=")
|
|
||||||
break
|
|
||||||
} else if strings.HasPrefix(string(line), "category=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "category=")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rdr.Reset(ini)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractDesktopInfo(desk *os.File) (name, category, iconName string) {
|
|
||||||
rdr := bufio.NewReader(desk)
|
|
||||||
var nameGot, catGot, iconGot bool
|
|
||||||
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
|
||||||
ln := string(line)
|
|
||||||
if !nameGot && strings.HasPrefix(ln, "Name=") {
|
|
||||||
name = strings.TrimPrefix(ln, "Name=")
|
|
||||||
nameGot = true
|
|
||||||
} else if !catGot && strings.HasPrefix(ln, "Categories=") {
|
|
||||||
cats := strings.Split(strings.TrimPrefix(ln, "Categories="), ";")
|
|
||||||
if len(cats) > 0 {
|
|
||||||
category = cats[0]
|
|
||||||
}
|
|
||||||
catGot = true
|
|
||||||
} else if !iconGot && strings.HasPrefix(ln, "Icon=") {
|
|
||||||
iconName = strings.TrimPrefix(ln, "Icon=")
|
|
||||||
iconGot = true
|
|
||||||
}
|
|
||||||
if nameGot && catGot && iconGot {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func getName(ini *os.File) string {
|
|
||||||
rdr := bufio.NewReader(ini)
|
|
||||||
var ret string
|
|
||||||
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
|
||||||
if strings.HasPrefix(string(line), "Name=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "Name=")
|
|
||||||
break
|
|
||||||
} else if strings.HasPrefix(string(line), "name=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "name=")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rdr.Reset(ini)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIcon(fold string) *gdk.Pixbuf {
|
|
||||||
var pic string
|
|
||||||
if _, err := os.Open(fold + "/appicon.png"); err == nil {
|
|
||||||
pic = fold + "/appicon.png"
|
|
||||||
} else if folder, err := os.Open(fold + "/App/AppInfo"); err == nil {
|
|
||||||
fis, _ := folder.Readdir(-1)
|
|
||||||
var pics []string
|
|
||||||
for _, v := range fis {
|
|
||||||
if !v.IsDir() && strings.HasSuffix(strings.ToLower(v.Name()), ".png") && strings.HasPrefix(strings.ToLower(v.Name()), "appicon_") {
|
|
||||||
pics = append(pics, v.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(pics)
|
|
||||||
if len(pics) > 1 {
|
|
||||||
var ind int
|
|
||||||
if !contains(pics, "appicon_32.png") {
|
|
||||||
ind = len(pics) - 1
|
|
||||||
} else {
|
|
||||||
ind = sort.SearchStrings(pics, "appicon_32.png")
|
|
||||||
}
|
|
||||||
pic = fold + "/App/AppInfo/" + pics[ind]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
img, _ := gtk.ImageNewFromIconName("application-x-executable", gtk.ICON_SIZE_BUTTON)
|
|
||||||
buf := img.GetPixbuf()
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
img, _ := gtk.ImageNewFromFile(pic)
|
|
||||||
buf, _ := img.GetPixbuf().ScaleSimple(32, 32, gdk.INTERP_BILINEAR)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
func findInfo(fold string) *os.File {
|
|
||||||
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
|
|
||||||
return fi
|
|
||||||
}
|
|
||||||
tmp, err := os.Open(fold + "/App/AppInfo")
|
|
||||||
if err == nil {
|
|
||||||
fis, _ := tmp.Readdirnames(-1)
|
|
||||||
for _, v := range fis {
|
|
||||||
if strings.ToLower(v) == "appinfo.ini" {
|
|
||||||
tmp, _ := os.Open(fold + "/App/AppInfo/" + v)
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gotk3/gotk3/glib"
|
|
||||||
"github.com/gotk3/gotk3/gtk"
|
|
||||||
"github.com/pkg/browser"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ui(win *gtk.Window) {
|
|
||||||
ls := getCatRows()
|
|
||||||
var treeApps []*gtk.TreeIter
|
|
||||||
header, _ := gtk.HeaderBarNew()
|
|
||||||
header.SetShowCloseButton(true)
|
|
||||||
header.SetTitle("LinuxPA")
|
|
||||||
header.SetSubtitle("PortableApps.com type launcher")
|
|
||||||
settings, _ := gtk.ButtonNewFromIconName("applications-system", gtk.ICON_SIZE_SMALL_TOOLBAR)
|
|
||||||
settings.SetTooltipText("Settings")
|
|
||||||
dnl, _ := gtk.ButtonNewFromIconName("emblem-downloads", gtk.ICON_SIZE_SMALL_TOOLBAR)
|
|
||||||
dnl.SetTooltipText("Download Apps")
|
|
||||||
header.PackStart(settings)
|
|
||||||
header.PackEnd(dnl)
|
|
||||||
win.SetTitlebar(header)
|
|
||||||
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
|
||||||
lrBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
|
||||||
catList, _ := gtk.ListBoxNew()
|
|
||||||
catList.SetActivateOnSingleClick(true)
|
|
||||||
store, _ := gtk.TreeStoreNew(glib.TYPE_OBJECT, glib.TYPE_STRING)
|
|
||||||
appsList, _ := gtk.TreeViewNewWithModel(store)
|
|
||||||
render, _ := gtk.CellRendererPixbufNew()
|
|
||||||
pixColumn, _ := gtk.TreeViewColumnNewWithAttribute("", render, "pixbuf", 0)
|
|
||||||
txtRender, _ := gtk.CellRendererTextNew()
|
|
||||||
txtColumn, _ := gtk.TreeViewColumnNewWithAttribute("", txtRender, "text", 1)
|
|
||||||
appsList.AppendColumn(pixColumn)
|
|
||||||
appsList.AppendColumn(txtColumn)
|
|
||||||
appsList.SetHeadersVisible(false)
|
|
||||||
catList.SetHExpand(true)
|
|
||||||
catList.SetVExpand(true)
|
|
||||||
appsList.SetHExpand(true)
|
|
||||||
appsList.SetVExpand(true)
|
|
||||||
vScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
hScrollCat, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
vScrollApp, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
hScrollApp, _ := gtk.AdjustmentNew(0, 0, 0, 0, 0, 0)
|
|
||||||
catScrl, _ := gtk.ScrolledWindowNew(hScrollCat, vScrollCat)
|
|
||||||
catScrl.Add(catList)
|
|
||||||
catScrl.SetSizeRequest(170, 500)
|
|
||||||
appScrl, _ := gtk.ScrolledWindowNew(hScrollApp, vScrollApp)
|
|
||||||
appScrl.Add(appsList)
|
|
||||||
appScrl.SetSizeRequest(300, 500)
|
|
||||||
lrBox.Add(catScrl)
|
|
||||||
lrBox.Add(appScrl)
|
|
||||||
botBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2)
|
|
||||||
botBox.SetMarginStart(10)
|
|
||||||
botBox.SetMarginEnd(10)
|
|
||||||
botBox.SetMarginTop(10)
|
|
||||||
botBox.SetMarginBottom(10)
|
|
||||||
edit, _ := gtk.ButtonNewWithLabel("Edit App..")
|
|
||||||
edit.Connect("clicked", func() {
|
|
||||||
selec, _ := appsList.GetSelection()
|
|
||||||
_, it, ok := selec.GetSelected()
|
|
||||||
if ok {
|
|
||||||
pth, _ := store.GetPath(it)
|
|
||||||
ind := pth.GetIndices()
|
|
||||||
if wine {
|
|
||||||
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
|
||||||
appLnch.edit(win, func() {
|
|
||||||
store.Clear()
|
|
||||||
for i := range ls {
|
|
||||||
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
|
||||||
}
|
|
||||||
ls = getCatRows()
|
|
||||||
for i, v := range ls {
|
|
||||||
catList.Insert(v, i)
|
|
||||||
}
|
|
||||||
catList.ShowAll()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
|
||||||
appLnch.edit(win, func() {
|
|
||||||
store.Clear()
|
|
||||||
for i := range ls {
|
|
||||||
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
|
||||||
}
|
|
||||||
ls = getCatRows()
|
|
||||||
for i, v := range ls {
|
|
||||||
catList.Insert(v, i)
|
|
||||||
}
|
|
||||||
catList.ShowAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
botBox.PackEnd(edit, false, false, 0)
|
|
||||||
topLvl.Add(lrBox)
|
|
||||||
topLvl.PackEnd(botBox, false, true, 0)
|
|
||||||
win.Add(topLvl)
|
|
||||||
for _, v := range ls {
|
|
||||||
catList.Add(v)
|
|
||||||
}
|
|
||||||
catList.Connect("row-selected", func() {
|
|
||||||
store.Clear()
|
|
||||||
if catList.GetSelectedRow().GetIndex() >= 0 {
|
|
||||||
treeApps = make([]*gtk.TreeIter, 0)
|
|
||||||
if wine {
|
|
||||||
apps := master[cats[catList.GetSelectedRow().GetIndex()]]
|
|
||||||
for _, v := range apps {
|
|
||||||
treeApps = append(treeApps, v.getTreeIter(store))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
apps := linmaster[lin[catList.GetSelectedRow().GetIndex()]]
|
|
||||||
for _, v := range apps {
|
|
||||||
treeApps = append(treeApps, v.getTreeIter(store))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
appsList.Connect("row-activated", func() {
|
|
||||||
selec, _ := appsList.GetSelection()
|
|
||||||
_, it, ok := selec.GetSelected()
|
|
||||||
if ok {
|
|
||||||
pth, _ := store.GetPath(it)
|
|
||||||
ind := pth.GetIndices()
|
|
||||||
if len(ind) == 1 {
|
|
||||||
if wine {
|
|
||||||
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
|
||||||
appLnch.launch()
|
|
||||||
} else {
|
|
||||||
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
|
||||||
appLnch.launch()
|
|
||||||
}
|
|
||||||
} else if len(ind) == 2 {
|
|
||||||
if wine {
|
|
||||||
appLnch := master[cats[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
|
||||||
appLnch.launchSub(ind[1])
|
|
||||||
} else {
|
|
||||||
appLnch := linmaster[lin[catList.GetSelectedRow().GetIndex()]][ind[0]]
|
|
||||||
appLnch.launchSub(ind[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
dnl.Connect("clicked", func() {
|
|
||||||
//TODO: detect if a webbrowser app is available and use that instead
|
|
||||||
browser.OpenURL("https://appimage.github.io/apps/")
|
|
||||||
})
|
|
||||||
settings.Connect("clicked", func() {
|
|
||||||
settingsUI(win, func() {
|
|
||||||
store.Clear()
|
|
||||||
for i := range ls {
|
|
||||||
catList.Remove(catList.GetRowAtIndex(len(ls) - i - 1))
|
|
||||||
}
|
|
||||||
ls = getCatRows()
|
|
||||||
for i, v := range ls {
|
|
||||||
catList.Insert(v, i)
|
|
||||||
}
|
|
||||||
catList.ShowAll()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCatRows() (out []*gtk.Label) {
|
|
||||||
if wine {
|
|
||||||
for _, v := range cats {
|
|
||||||
txt, _ := gtk.LabelNew(v)
|
|
||||||
out = append(out, txt)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, v := range lin {
|
|
||||||
txt, _ := gtk.LabelNew(v)
|
|
||||||
out = append(out, txt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/gtk"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
versionURL = "https://www.dropbox.com/s/a0xizzo0a4vsfqt/Version?dl=1"
|
|
||||||
downloadURL = "https://github.com/CalebQ42/LinuxPA/releases/download/vXXX/LinuxPA"
|
|
||||||
changelogURL = "https://www.dropbox.com/s/rk8ec9p14imkh03/Changelog?dl=1"
|
|
||||||
changelogBetaURL = "https://www.dropbox.com/s/h2u34g5s8qr8sef/ChangelogBeta?dl=1"
|
|
||||||
)
|
|
||||||
|
|
||||||
//Thanks to https://www.socketloop.com/tutorials/golang-download-file-example
|
|
||||||
//For some of the code
|
|
||||||
|
|
||||||
//Returns if success
|
|
||||||
func versionDL() (bool, error) {
|
|
||||||
versionFile, err := os.Create("PortableApps/LinuxPACom/Version")
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
versionFile.Chmod(0777)
|
|
||||||
check := http.Client{
|
|
||||||
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
|
|
||||||
r.URL.Opaque = r.URL.Path
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
response, err := check.Get(versionURL)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
_, err = io.Copy(versionFile, response.Body)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVersionFileInfo() (stable string, beta string) {
|
|
||||||
fil, err := os.Open("PortableApps/LinuxPACom/Version")
|
|
||||||
if err != nil {
|
|
||||||
return "Error!", ""
|
|
||||||
}
|
|
||||||
rdr := bufio.NewReader(fil)
|
|
||||||
out, _, _ := rdr.ReadLine()
|
|
||||||
stable = string(out)
|
|
||||||
out, _, _ = rdr.ReadLine()
|
|
||||||
beta = string(out)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func changelogDL() (bool, error) {
|
|
||||||
changelogFile, err := os.Create("PortableApps/LinuxPACom/Changelog")
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
changelogFile.Chmod(0777)
|
|
||||||
check := http.Client{
|
|
||||||
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
|
|
||||||
r.URL.Opaque = r.URL.Path
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
var response *http.Response
|
|
||||||
if betaUpdate {
|
|
||||||
response, err = check.Get(changelogBetaURL)
|
|
||||||
} else {
|
|
||||||
response, err = check.Get(changelogURL)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
_, err = io.Copy(changelogFile, response.Body)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getChangelog() string {
|
|
||||||
fil, err := os.Open("PortableApps/LinuxPACom/Changelog")
|
|
||||||
if err != nil {
|
|
||||||
return "Error!"
|
|
||||||
}
|
|
||||||
out, _ := ioutil.ReadAll(fil)
|
|
||||||
return string(out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkForUpdate(stable, beta string) (bool, error) {
|
|
||||||
new := stable
|
|
||||||
if betaUpdate {
|
|
||||||
new = beta
|
|
||||||
}
|
|
||||||
curSlice := strings.Split(version, ".")
|
|
||||||
newSlice := strings.Split(new, ".")
|
|
||||||
curNums := make([]int, 4)
|
|
||||||
newNums := make([]int, 4)
|
|
||||||
for i, v := range curSlice {
|
|
||||||
num, err := strconv.Atoi(v)
|
|
||||||
if err == nil {
|
|
||||||
curNums[i] = num
|
|
||||||
}
|
|
||||||
num, err = strconv.Atoi(newSlice[i])
|
|
||||||
if err == nil {
|
|
||||||
newNums[i] = num
|
|
||||||
} else {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if newNums[i] > curNums[i] {
|
|
||||||
return true, nil
|
|
||||||
} else if curNums[i] > newNums[i] {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadUpdate(newVersion string) (bool, error) {
|
|
||||||
url := strings.Replace(downloadURL, "XXX", newVersion, -1)
|
|
||||||
err := os.Rename("LinuxPA", ".LinuxPA.old")
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
fil, err := os.Create("LinuxPA")
|
|
||||||
fil.Chmod(0777)
|
|
||||||
defer fil.Close()
|
|
||||||
if err != nil {
|
|
||||||
os.Rename(".LinuxPA.old", "LinuxPA")
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
check := http.Client{
|
|
||||||
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
|
|
||||||
r.URL.Opaque = r.URL.Path
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
re, err := check.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer re.Body.Close()
|
|
||||||
_, err = io.Copy(fil, re.Body)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(win *gtk.Window, forced bool) {
|
|
||||||
stat, err := versionDL()
|
|
||||||
if stat {
|
|
||||||
stable, beta := getVersionFileInfo()
|
|
||||||
if stable != "Error!" {
|
|
||||||
stat, err = checkForUpdate(stable, beta)
|
|
||||||
if stat || forced {
|
|
||||||
stat, err = changelogDL()
|
|
||||||
if stat {
|
|
||||||
updateWin, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
||||||
updateWin.SetTransientFor(win)
|
|
||||||
updateWin.SetPosition(gtk.WIN_POS_CENTER)
|
|
||||||
updateWin.SetDefaultSize(600, 300)
|
|
||||||
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
lbl, _ := gtk.LabelNew("There's a new update! Here's the changelog:")
|
|
||||||
tagTbl, _ := gtk.TextTagTableNew()
|
|
||||||
buf, _ := gtk.TextBufferNew(tagTbl)
|
|
||||||
tv, _ := gtk.TextViewNewWithBuffer(buf)
|
|
||||||
tv.SetWrapMode(gtk.WRAP_WORD)
|
|
||||||
tv.SetEditable(false)
|
|
||||||
buf.SetText(getChangelog())
|
|
||||||
butBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
|
|
||||||
upBut, _ := gtk.ButtonNewWithLabel("Update")
|
|
||||||
upBut.Connect("clicked", func() {
|
|
||||||
updateWin.Close()
|
|
||||||
actuallyUpdate(win, forced)
|
|
||||||
})
|
|
||||||
cnlBut, _ := gtk.ButtonNewWithLabel("Cancel")
|
|
||||||
cnlBut.Connect("clicked", func() {
|
|
||||||
updateWin.Close()
|
|
||||||
})
|
|
||||||
butBox.Add(upBut)
|
|
||||||
butBox.Add(cnlBut)
|
|
||||||
topLvl.Add(lbl)
|
|
||||||
topLvl.Add(tv)
|
|
||||||
topLvl.Add(butBox)
|
|
||||||
topLvl.SetMarginBottom(10)
|
|
||||||
topLvl.SetMarginEnd(10)
|
|
||||||
topLvl.SetMarginStart(10)
|
|
||||||
topLvl.SetMarginTop(10)
|
|
||||||
updateWin.Add(topLvl)
|
|
||||||
updateWin.ShowAll()
|
|
||||||
updateWin.Show()
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("Failed Version File Info")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func actuallyUpdate(win *gtk.Window, forced bool) {
|
|
||||||
updateWin, _ := gtk.WindowNew(gtk.WINDOW_POPUP)
|
|
||||||
updateWin.SetTransientFor(win)
|
|
||||||
updateWin.SetSizeRequest(150, 50)
|
|
||||||
topLvl, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
spin, _ := gtk.SpinnerNew()
|
|
||||||
spin.Start()
|
|
||||||
lbl, _ := gtk.LabelNew("Updating")
|
|
||||||
topLvl.Add(spin)
|
|
||||||
topLvl.Add(lbl)
|
|
||||||
topLvl.SetMarginBottom(10)
|
|
||||||
topLvl.SetMarginEnd(10)
|
|
||||||
topLvl.SetMarginStart(10)
|
|
||||||
topLvl.SetMarginTop(10)
|
|
||||||
updateWin.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
|
||||||
updateWin.Add(topLvl)
|
|
||||||
updateWin.ShowAll()
|
|
||||||
updateWin.Show()
|
|
||||||
go func(win, updateWin *gtk.Window) {
|
|
||||||
defer updateWin.Close()
|
|
||||||
stat, err := versionDL()
|
|
||||||
if stat {
|
|
||||||
stable, beta := getVersionFileInfo()
|
|
||||||
if stable != "Error!" {
|
|
||||||
stat, err = checkForUpdate(stable, beta)
|
|
||||||
if stat || forced {
|
|
||||||
if betaUpdate {
|
|
||||||
downloadUpdate(beta)
|
|
||||||
} else {
|
|
||||||
downloadUpdate(stable)
|
|
||||||
}
|
|
||||||
win.Close()
|
|
||||||
cmd := exec.Command("./LinuxPA")
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Start()
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("Failed Version File Info")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}(win, updateWin)
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/gtk"
|
|
||||||
"github.com/mholt/archiver/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
wineURL = "https://www.playonlinux.com/wine/binaries/phoenicis/staging-linux-amd64/PlayOnLinux-wine-5.20-staging-linux-amd64.tar.gz"
|
|
||||||
)
|
|
||||||
|
|
||||||
func downloadWine(parent *gtk.Window, cb chan bool) {
|
|
||||||
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
||||||
win.SetTransientFor(parent)
|
|
||||||
win.SetDestroyWithParent(true)
|
|
||||||
win.Connect("destroy", func() {
|
|
||||||
parent.SetSensitive(true)
|
|
||||||
})
|
|
||||||
parent.SetSensitive(false)
|
|
||||||
spin, _ := gtk.SpinnerNew()
|
|
||||||
spin.Start()
|
|
||||||
txt, _ := gtk.LabelNew("Downloading Wine")
|
|
||||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
|
|
||||||
box.SetMarginBottom(10)
|
|
||||||
box.SetMarginEnd(10)
|
|
||||||
box.SetMarginStart(10)
|
|
||||||
box.SetMarginTop(10)
|
|
||||||
box.Add(spin)
|
|
||||||
box.Add(txt)
|
|
||||||
win.Add(box)
|
|
||||||
win.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
|
|
||||||
win.ShowAll()
|
|
||||||
win.Show()
|
|
||||||
go func(win *gtk.Window, txt *gtk.Label) {
|
|
||||||
defer win.Close()
|
|
||||||
wineTar, err := os.Create("PortableApps/LinuxPACom/wine5.20.tar.bz2")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
cb <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer wineTar.Close()
|
|
||||||
check := http.Client{
|
|
||||||
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
|
|
||||||
r.URL.Opaque = r.URL.Path
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
resp, err := check.Get(wineURL)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
cb <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
os.RemoveAll("PortableApps/LinuxPACom/Wine")
|
|
||||||
defer resp.Body.Close()
|
|
||||||
_, err = io.Copy(wineTar, resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
cb <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
txt.SetText("Extracting Wine")
|
|
||||||
err = archiver.DefaultTarBz2.Unarchive("PortableApps/LinuxPACom/wine2.5.tar.bz2", "PortableApps/LinuxPACom/Wine")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
cb <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fil, err := os.Open("PortableApps/LinuxPACom/common.sh")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
cb <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tmp, err := ioutil.ReadAll(fil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
cb <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !strings.Contains(string(tmp), "export PATH=$PWD/PortableApps/LinuxPACom/Wine/wineversion/2.5/bin:$PATH") {
|
|
||||||
tmp = append(tmp, []byte("\nexport PATH=$PWD/PortableApps/LinuxPACom/Wine/wineversion/2.5/bin:$PATH")...)
|
|
||||||
ioutil.WriteFile("PortableApps/LinuxPACom/common.sh", tmp, 0777)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
cb <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cb <- true
|
|
||||||
return
|
|
||||||
}(win, txt)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user