hbspbar

bspwm status bar
git clone https://hhvn.uk/hbspbar
git clone git://hhvn.uk/hbspbar
Log | Files | Refs

bar.go (3440B)


      1 package main
      2 
      3 import (
      4 	"image"
      5 	"errors"
      6 	"image/color"
      7 
      8 	"hhvn.uk/hbspbar/config"
      9 	"hhvn.uk/hbspbar/status"
     10 	"hhvn.uk/hbspbar/bspc"
     11 	"hhvn.uk/hbspbar/drw"
     12 )
     13 
     14 var bars map[int]*bar = make(map[int]*bar)
     15 
     16 type bar struct {
     17 	id      int
     18 	w       *drw.Window
     19 	i       *image.RGBA
     20 }
     21 
     22 var (
     23 	ErrNoState = errors.New("attempted to create a bar with uninitialized state")
     24 	ErrNoSuchBar = errors.New("attempted to destroy non-existant bar")
     25 ) 
     26  
     27 func (b *bar) init(id int, state *bspc.State) error {
     28 	b.id = id
     29 	b.i  = nil
     30 
     31 	mon, err := b.getmon(state)
     32 	if err != nil { return err }
     33 
     34 	go mon.TopPadding(config.H)
     35 
     36 	geom := mon.Rectangle
     37 
     38 	b.w, err = drw.WindowCreate(geom.X, geom.Y, geom.Width, config.H)
     39 	if err != nil { return err }
     40 
     41 	rect := image.Rect(0, 0, int(mon.Rectangle.Width), int(config.H))
     42 	b.i = image.NewRGBA(rect)
     43 
     44 	return nil
     45 }
     46 
     47 func (b *bar) destroy(state *bspc.State) {
     48 	mon, _ := b.getmon(state)
     49 	if (mon != nil) {
     50 		mon.TopPadding(0)
     51 	}
     52 }
     53 
     54 func (b bar) getmon(state *bspc.State) (*bspc.Monitor, error) {
     55 	return state.GetMon(b.id)
     56 }
     57 
     58 func (b *bar) drawText(x int, col color.Color, text string) (int, error) {
     59 	return drw.DrawText(b.i, x, col, text)
     60 }
     61 
     62 func (b *bar) drawRect(x, y, w, h int, c color.Color, fill bool) {
     63 	drw.DrawRect(b.i, x, y, w, h, c, fill)
     64 }
     65 
     66 func (b bar) draw(state *bspc.State, blocks []*status.Block) error {
     67 	var bg     color.Color
     68 	var filled bool
     69 
     70 	if blocks == nil {
     71 		return nil
     72 	}
     73 
     74 	mon, err := b.getmon(state)
     75 	if err != nil {
     76 		return err
     77 	}
     78 
     79 	// Dimensions of drawing space
     80 	cx := 0
     81 	w  := int(mon.Rectangle.Width)
     82 	h  := int(config.H)
     83 
     84 
     85 	// Draw background
     86 	b.drawRect(0, 0, w, h, config.Bg, true)
     87 
     88 	// Monitor
     89 	montext := mon.Name
     90 	monw    := 6 + drw.TextWidth(montext) + 8
     91 
     92 	if mon.Focused {
     93 		bg = config.Sel
     94 	} else {
     95 		bg = config.UnselMon
     96 	}
     97 
     98 	b.drawRect(cx, 0, monw, h, bg, true)
     99 	b.drawText(cx + 6, config.Fg, montext)
    100 	cx += monw
    101 
    102 	// Desktops
    103 	boxw := 4
    104 	ds   := len(mon.Desktops)
    105 	dw   := 4 + (4 + boxw + 2 + 3) * ds + 5
    106 
    107 	for i := 0; i < ds; i++ {
    108 		dw += drw.TextWidth(mon.Desktops[i].Name)
    109 	}
    110 
    111 	cx += 4
    112 	for i := 0; i < ds; i++ {
    113 		d := mon.Desktops[i]
    114 
    115 		cx += 5
    116 
    117 		switch {
    118 		case d.Urgent(): bg = config.Urg
    119 		case d.Focused:  bg = config.Sel
    120 		default:         bg = config.FgDark
    121 		}
    122 
    123 		filled = d.Root != nil
    124 
    125 		b.drawRect(cx, 3, boxw, h - 7, bg, filled)
    126 		cx += boxw + 2
    127 		ax, _ := b.drawText(cx, config.Fg, d.Name)
    128 		cx += ax + 2
    129 	}
    130 
    131 	cx = int(mon.Rectangle.Width)
    132 	for _, s := range blocks {
    133 		if s != nil {
    134 			cx -= s.W
    135 			cx -= config.StatusPad
    136 		}
    137 	}
    138 
    139 	b.drawRect(cx, 0, int(mon.Rectangle.Width) - cx, int(config.H),
    140 		config.Status, true)
    141 
    142 	cx += config.StatusPad / 2
    143 
    144 	for _, s := range blocks {
    145 		if s != nil {
    146 			drw.AddImg(b.i, cx, s.W, s.I)
    147 
    148 			cx += s.W + config.StatusPad
    149 		}
    150 	}
    151 
    152 	b.w.Paint(b.i)
    153 
    154 	return nil
    155 }
    156 
    157 func Create(state *bspc.State, id int) (error) {
    158 	var b bar
    159 
    160 	if state == nil {
    161 		return ErrNoState
    162 	}
    163 
    164 	if _, ok := bars[id]; ok {
    165 		// Already created, whatever.
    166 		return nil
    167 	}
    168 
    169 	if err := b.init(id, state); err != nil {
    170 		return err
    171 	}
    172 
    173 	bars[b.id] = &b
    174 	return nil
    175 }
    176 
    177 func Redraw(state *bspc.State, blocks []*status.Block) {
    178 	for _, b := range bars {
    179 		b.draw(state, blocks)
    180 	}
    181 }
    182 
    183 func Destroy(state *bspc.State, id int) error {
    184 	b, ok := bars[id]
    185 	if !ok {
    186 		return ErrNoSuchBar
    187 	}
    188 
    189 	b.destroy(state)
    190 	delete(bars, id)
    191 
    192 	return nil
    193 }
    194 
    195 func Cleanup(state *bspc.State) {
    196 	if state != nil {
    197 		for _, b := range bars {
    198 			b.destroy(state)
    199 		}
    200 	}
    201 }