Small changes, update readme.
This commit is contained in:
parent
533d788cbb
commit
e109215a0b
75
README.md
75
README.md
@ -1,12 +1,85 @@
|
|||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/onodera-punpun/melonbar)](https://goreportcard.com/report/github.com/onodera-punpun/melonbar)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/onodera-punpun/melonbar)](https://goreportcard.com/report/github.com/onodera-punpun/melonbar)
|
||||||
|
|
||||||
melonbar - A Concurrent, hackable bar/panel for X written in Go.
|
melonbar - A concurrent, hackable bar/panel for X written in Go.
|
||||||
|
|
||||||
|
|
||||||
## INSTALLATION
|
## INSTALLATION
|
||||||
|
|
||||||
`go get github.com/onodera-punpun/melonbar`
|
`go get github.com/onodera-punpun/melonbar`
|
||||||
|
|
||||||
|
`melonbar` depends on Go 1.9 or newer.
|
||||||
|
|
||||||
|
|
||||||
|
## USAGE
|
||||||
|
|
||||||
|
So the idea is that this bar is very "easy" to configure by just
|
||||||
|
modifying the source code, à la suckless.
|
||||||
|
|
||||||
|
Users can modify, configure and create new "blocks" in `blocks.go`.
|
||||||
|
and configure the position, width and font of the bar in `main.go`.
|
||||||
|
|
||||||
|
|
||||||
|
## CREATING A BLOCK FUNCTIONS
|
||||||
|
|
||||||
|
On top of each block function you should run `bar.initBlock()`, this
|
||||||
|
is where most of the configuration happens. Here is a short
|
||||||
|
explanation of each parameter from left to right:
|
||||||
|
|
||||||
|
* The name of the block, this is and gets used as the name
|
||||||
|
of the block map key. (`string`)
|
||||||
|
* The initial string the block should display. (`string`)
|
||||||
|
* The width of the block. (`int`)
|
||||||
|
* The aligment of the text, this can be `'l'` for left aligment, `'c'`
|
||||||
|
for center aligment and `'r'` for right aligment. (`rune`)
|
||||||
|
* Additional x offset to further tweak the location of the text.
|
||||||
|
(`int`)
|
||||||
|
* The foreground color of the block in hexadecimal. (`string`)
|
||||||
|
* The background color of the block in hexadecimal. (`string`)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Everything that should not be ran in a loop should of course be
|
||||||
|
specified before the `for` loop. For example setting up a connection
|
||||||
|
to mpd.
|
||||||
|
|
||||||
|
If you want something to only be done *after* the very first loop - an
|
||||||
|
example of this would be not waiting for a workspace chance event, but
|
||||||
|
immediately checking the current workspace. - use:
|
||||||
|
|
||||||
|
```go
|
||||||
|
init := true
|
||||||
|
for {
|
||||||
|
if !init {
|
||||||
|
// Things you only want to do after the first loop.
|
||||||
|
}
|
||||||
|
init = false
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
This can be helpful because else the bar would display `"?"` before
|
||||||
|
the user changes his workspace for the first time.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
When you've gathered all needed information you can:
|
||||||
|
|
||||||
|
* Update the foreground color of the block using
|
||||||
|
`bar.updateBlockFg()`. This function takes two parameters, the first
|
||||||
|
one being the block map key, and the second one the new string the
|
||||||
|
new foreground color of the block, in hexadecimal.
|
||||||
|
* Update the background color of the block using
|
||||||
|
`bar.updateBlockBg()`. This function takes the same parameters as
|
||||||
|
`bar.updateBlockFg()`.
|
||||||
|
* Update the text of the block using `bar.updateBlockTxt()`. Again,
|
||||||
|
this function takes two parameters, the second one being the new
|
||||||
|
string the block should display.
|
||||||
|
|
||||||
|
Agter having ran the required `updateBlock*` functions you must run
|
||||||
|
`bar.redraw <- "blockname"`, where blockname is the name of the block
|
||||||
|
map key.
|
||||||
|
|
||||||
|
|
||||||
## AUTHORS
|
## AUTHORS
|
||||||
|
|
||||||
|
52
bar.go
52
bar.go
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -17,13 +16,6 @@ import (
|
|||||||
|
|
||||||
// Bar is a struct with information about the bar.
|
// Bar is a struct with information about the bar.
|
||||||
type Bar struct {
|
type Bar struct {
|
||||||
// The width and height of the bar.
|
|
||||||
w, h int
|
|
||||||
|
|
||||||
// This is a sum of all of the block widths, used to draw a block
|
|
||||||
// to the right of the last block.
|
|
||||||
xsum int
|
|
||||||
|
|
||||||
// Connection to the X server, the abe window, and the bar image.
|
// Connection to the X server, the abe window, and the bar image.
|
||||||
xu *xgbutil.XUtil
|
xu *xgbutil.XUtil
|
||||||
win *xwindow.Window
|
win *xwindow.Window
|
||||||
@ -33,6 +25,13 @@ type Bar struct {
|
|||||||
font *truetype.Font
|
font *truetype.Font
|
||||||
fontSize float64
|
fontSize float64
|
||||||
|
|
||||||
|
// The width and height of the bar.
|
||||||
|
w, h int
|
||||||
|
|
||||||
|
// This is a sum of all of the block widths, used to draw a block
|
||||||
|
// to the right of the last block.
|
||||||
|
xsum int
|
||||||
|
|
||||||
// A map with information about the block, see `Block`.
|
// A map with information about the block, see `Block`.
|
||||||
block *sync.Map
|
block *sync.Map
|
||||||
|
|
||||||
@ -49,10 +48,13 @@ type Block struct {
|
|||||||
// The x coordinate and width of the bar.
|
// The x coordinate and width of the bar.
|
||||||
x, w int
|
x, w int
|
||||||
|
|
||||||
// How to align the text, 'l' for left, 'c' for center and 'r' for
|
/// The aligment of the text, this can be `'l'` for left aligment,
|
||||||
// right.
|
// `'c'` for center aligment and `'r'` for right aligment.
|
||||||
align rune
|
align rune
|
||||||
|
|
||||||
|
// Additional x offset to further tweak the location of the text.
|
||||||
|
xoff int
|
||||||
|
|
||||||
// The foreground and background colors.
|
// The foreground and background colors.
|
||||||
bg, fg xgraphics.BGRA
|
bg, fg xgraphics.BGRA
|
||||||
|
|
||||||
@ -65,9 +67,6 @@ func initBar(x, y, w, h int, font string, fontSize float64) (*Bar,
|
|||||||
bar := new(Bar)
|
bar := new(Bar)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
bar.w = w
|
|
||||||
bar.h = h
|
|
||||||
|
|
||||||
// Connect to X.
|
// Connect to X.
|
||||||
bar.xu, err = xgbutil.NewConn()
|
bar.xu, err = xgbutil.NewConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -107,15 +106,18 @@ func initBar(x, y, w, h int, font string, fontSize float64) (*Bar,
|
|||||||
}
|
}
|
||||||
bar.fontSize = fontSize
|
bar.fontSize = fontSize
|
||||||
|
|
||||||
|
bar.w = w
|
||||||
|
bar.h = h
|
||||||
|
|
||||||
bar.block = new(sync.Map)
|
bar.block = new(sync.Map)
|
||||||
bar.redraw = make(chan string)
|
bar.redraw = make(chan string)
|
||||||
|
|
||||||
return bar, nil
|
return bar, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) initBlock(name string, width int, align rune, txt, bg,
|
func (bar *Bar) initBlock(name, txt string, width int, align rune,
|
||||||
fg string) {
|
xoff int, bg, fg string) {
|
||||||
bar.block.Store(name, &Block{txt, bar.xsum, width, align,
|
bar.block.Store(name, &Block{txt, bar.xsum, width, align, xoff,
|
||||||
hexToBGRA(bg), hexToBGRA(fg), bar.img.SubImage(image.Rect(
|
hexToBGRA(bg), hexToBGRA(fg), bar.img.SubImage(image.Rect(
|
||||||
bar.xsum, 0, bar.xsum+width, bar.h)).(*xgraphics.Image)})
|
bar.xsum, 0, bar.xsum+width, bar.h)).(*xgraphics.Image)})
|
||||||
bar.xsum += width
|
bar.xsum += width
|
||||||
@ -142,9 +144,9 @@ func (bar *Bar) updateBlockTxt(name, txt string) {
|
|||||||
block.txt = txt
|
block.txt = txt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) draw(name string) {
|
func (bar *Bar) draw(name string) error {
|
||||||
// Needed to prevent a `interface conversion: interface {} is nil,
|
// Needed to prevent an `interface conversion: interface {} is
|
||||||
// not *main.Block` panic for some reason...
|
// nil, not *main.Block` panic for some reason...
|
||||||
time.Sleep(time.Nanosecond)
|
time.Sleep(time.Nanosecond)
|
||||||
|
|
||||||
i, _ := bar.block.Load(name)
|
i, _ := bar.block.Load(name)
|
||||||
@ -155,27 +157,29 @@ func (bar *Bar) draw(name string) {
|
|||||||
return block.bg
|
return block.bg
|
||||||
})
|
})
|
||||||
|
|
||||||
// Calculate the required x for the different aligments.
|
// Calculate the required x coordinate for the different
|
||||||
|
// aligments.
|
||||||
var x int
|
var x int
|
||||||
switch block.align {
|
switch block.align {
|
||||||
case 'l':
|
case 'l':
|
||||||
x = block.x
|
x = block.x + block.xoff
|
||||||
case 'c':
|
case 'c':
|
||||||
tw, _ := xgraphics.Extents(bar.font, bar.fontSize, block.txt)
|
tw, _ := xgraphics.Extents(bar.font, bar.fontSize, block.txt)
|
||||||
x = block.x + ((block.w / 2) - (tw / 2))
|
x = block.x + ((block.w / 2) - (tw / 2)) + block.xoff
|
||||||
case 'r':
|
case 'r':
|
||||||
tw, _ := xgraphics.Extents(bar.font, bar.fontSize, block.txt)
|
tw, _ := xgraphics.Extents(bar.font, bar.fontSize, block.txt)
|
||||||
x = (block.x + block.w) - tw
|
x = (block.x + block.w) - tw + block.xoff
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Center vertically automatically.
|
// TODO: Center vertically automatically.
|
||||||
// Draw the text.
|
// Draw the text.
|
||||||
if _, _, err := block.img.Text(x, 6, block.fg, bar.fontSize,
|
if _, _, err := block.img.Text(x, 6, block.fg, bar.fontSize,
|
||||||
bar.font, block.txt); err != nil {
|
bar.font, block.txt); err != nil {
|
||||||
log.Fatal(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
block.img.XDraw()
|
block.img.XDraw()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) paint() {
|
func (bar *Bar) paint() {
|
||||||
|
53
blocks.go
53
blocks.go
@ -15,8 +15,8 @@ import (
|
|||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (bar *Bar) clockFun(width int, bg, fg string) {
|
func (bar *Bar) clockFun() {
|
||||||
bar.initBlock("clock", width, 'c', "?", bg, fg)
|
bar.initBlock("clock", "?", 800, 'c', 300, "#445967", "#CCCCCC")
|
||||||
|
|
||||||
init := true
|
init := true
|
||||||
for {
|
for {
|
||||||
@ -33,8 +33,8 @@ func (bar *Bar) clockFun(width int, bg, fg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) musicFun(width int, bg, fg string) {
|
func (bar *Bar) musicFun() error {
|
||||||
bar.initBlock("music", width, 'r', "?", bg, fg)
|
bar.initBlock("music", "?", 660, 'r', -10, "#3C4F5B", "#CCCCCC")
|
||||||
|
|
||||||
watcher, err := mpd.NewWatcher("tcp", ":6600", "", "player")
|
watcher, err := mpd.NewWatcher("tcp", ":6600", "", "player")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -82,8 +82,8 @@ func (bar *Bar) musicFun(width int, bg, fg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) todoFun(width int, bg, fg string) {
|
func (bar *Bar) todoFun() {
|
||||||
bar.initBlock("todo", width, 'c', "?", bg, fg)
|
bar.initBlock("todo", "?", 29, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
|
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -123,8 +123,8 @@ func (bar *Bar) todoFun(width int, bg, fg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) weatherFun(width int, bg, fg string) {
|
func (bar *Bar) weatherFun() {
|
||||||
bar.initBlock("weather", width, 'r', "?", bg, fg)
|
bar.initBlock("weather", "?", 29, 'r', 0, "#5394C9", "#FFFFFF")
|
||||||
|
|
||||||
w, err := owm.NewCurrent("C", "en")
|
w, err := owm.NewCurrent("C", "en")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -173,8 +173,8 @@ func (bar *Bar) weatherFun(width int, bg, fg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) windowFun(width int, bg, fg string) {
|
func (bar *Bar) windowFun() {
|
||||||
bar.initBlock("window", width, 'c', "?", bg, fg)
|
bar.initBlock("window", "?", 220, 'c', 0, "#37BF8D", "#FFFFFF")
|
||||||
|
|
||||||
init := true
|
init := true
|
||||||
var Owin string
|
var Owin string
|
||||||
@ -218,11 +218,10 @@ func (bar *Bar) windowFun(width int, bg, fg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) workspaceFun(widthWWW, widthIRC, widthSRC int, bgi,
|
func (bar *Bar) workspaceFun() {
|
||||||
bga, fg string) {
|
bar.initBlock("www", "www", 74, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
bar.initBlock("workspaceWWW", widthWWW, 'c', "www", bgi, fg)
|
bar.initBlock("irc", "irc", 67, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
bar.initBlock("workspaceIRC", widthIRC, 'c', "irc", bgi, fg)
|
bar.initBlock("src", "src", 70, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
bar.initBlock("workspaceSRC", widthSRC, 'c', "src", bgi, fg)
|
|
||||||
|
|
||||||
init := true
|
init := true
|
||||||
var Owsp uint
|
var Owsp uint
|
||||||
@ -258,20 +257,20 @@ func (bar *Bar) workspaceFun(widthWWW, widthIRC, widthSRC int, bgi,
|
|||||||
|
|
||||||
switch wsp {
|
switch wsp {
|
||||||
case 0:
|
case 0:
|
||||||
bar.updateBlockBg("workspaceWWW", bga)
|
bar.updateBlockBg("www", "#72A7D3")
|
||||||
bar.updateBlockBg("workspaceIRC", bgi)
|
bar.updateBlockBg("irc", "#5394C9")
|
||||||
bar.updateBlockBg("workspaceSRC", bgi)
|
bar.updateBlockBg("src", "#5394C9")
|
||||||
case 1:
|
case 1:
|
||||||
bar.updateBlockBg("workspaceWWW", bgi)
|
bar.updateBlockBg("www", "#5394C9")
|
||||||
bar.updateBlockBg("workspaceIRC", bga)
|
bar.updateBlockBg("irc", "#72A7D3")
|
||||||
bar.updateBlockBg("workspaceSRC", bgi)
|
bar.updateBlockBg("src", "#5394C9")
|
||||||
case 2:
|
case 2:
|
||||||
bar.updateBlockBg("workspaceWWW", bgi)
|
bar.updateBlockBg("www", "#5394C9")
|
||||||
bar.updateBlockBg("workspaceIRC", bgi)
|
bar.updateBlockBg("irc", "#5394C9")
|
||||||
bar.updateBlockBg("workspaceSRC", bga)
|
bar.updateBlockBg("src", "#72A7D3")
|
||||||
}
|
}
|
||||||
bar.redraw <- "workspaceWWW"
|
bar.redraw <- "www"
|
||||||
bar.redraw <- "workspaceIRC"
|
bar.redraw <- "irc"
|
||||||
bar.redraw <- "workspaceSRC"
|
bar.redraw <- "src"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
main.go
26
main.go
@ -6,27 +6,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
b, err := initBar(0, 0, 1920, 29, "/home/onodera/.fonts/cure.ttf",
|
bar, err := initBar(0, 0, 1920, 29,
|
||||||
11)
|
"/home/onodera/.fonts/cure.ttf", 11)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run bar block functions. Make sure to sleep a millisecond after
|
// Run bar block functions. Make sure to sleep a millisecond after
|
||||||
// each block, else they won't appear in the right order.
|
// each block, else they won't appear in the right order.
|
||||||
go b.windowFun(220, "#37BF8D", "#FFFFFF")
|
go bar.windowFun()
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
go b.workspaceFun(74, 67, 70, "#5394C9", "#72A7D3", "#FFFFFF")
|
|
||||||
|
go bar.workspaceFun()
|
||||||
time.Sleep(time.Millisecond * 3)
|
time.Sleep(time.Millisecond * 3)
|
||||||
go b.clockFun(900, "#445967", "#CCCCCC")
|
|
||||||
|
go bar.clockFun()
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
go b.musicFun(600, "#3C4F5B", "#CCCCCC")
|
|
||||||
|
go bar.musicFun()
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
|
||||||
|
go bar.todoFun()
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
//go b.todoFun(200)
|
|
||||||
//time.Sleep(time.Millisecond)
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
b.draw(<-b.redraw)
|
if err := bar.draw(<-bar.redraw); err != nil {
|
||||||
b.paint()
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
bar.paint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user