Codebase list golang-github-vbauerster-mpb / e806cc4 decor / merge.go
e806cc4

Tree @e806cc4 (Download .tar.gz)

merge.go @e806cc4raw · history · blame

package decor

import (
	"fmt"
	"strings"
	"unicode/utf8"
)

// Merge helper func, provides a way to synchronize width of single
// decorator with adjacent decorators of different bar, like so:
//   +--------+---------+
//   |     MERGE(D)     |
//   +--------+---------+
//   |   D1   |   D2    |
//   +--------+---------+
//
func Merge(decorator Decorator, placeholders ...WC) Decorator {
	if _, ok := decorator.Sync(); !ok || len(placeholders) == 0 {
		return decorator
	}
	md := &mergeDecorator{
		Decorator:    decorator,
		placeHolders: make([]*placeHolderDecorator, len(placeholders)),
	}
	md.wc = decorator.SetConfig(md.wc)
	for i, wc := range placeholders {
		wc.Init()
		md.placeHolders[i] = &placeHolderDecorator{
			WC:    wc,
			wsync: make(chan int),
		}
	}
	return md
}

type mergeDecorator struct {
	Decorator
	wc           WC
	placeHolders []*placeHolderDecorator
}

func (d *mergeDecorator) CompoundDecorators() []Decorator {
	decorators := make([]Decorator, len(d.placeHolders)+1)
	decorators[0] = d.Decorator
	for i, ph := range d.placeHolders {
		decorators[i+1] = ph
	}
	return decorators
}

func (md *mergeDecorator) Sync() (chan int, bool) {
	return md.wc.Sync()
}

func (d *mergeDecorator) Decor(st *Statistics) string {
	msg := d.Decorator.Decor(st)
	msgLen := utf8.RuneCountInString(msg)
	pWidth := msgLen / (len(d.placeHolders) + 1)
	mod := msgLen % (len(d.placeHolders) + 1)
	d.wc.wsync <- pWidth + mod
	for _, ph := range d.placeHolders {
		ph.wsync <- pWidth
	}
	max := <-d.wc.wsync
	for _, ph := range d.placeHolders {
		max += <-ph.wsync
	}
	if (d.wc.C & DextraSpace) != 0 {
		max++
	}
	return fmt.Sprintf(fmt.Sprintf(d.wc.dynFormat, max), msg)
}

type placeHolderDecorator struct {
	WC
	wsync chan int
}

func (d *placeHolderDecorator) Decor(st *Statistics) string {
	go func() {
		width := <-d.wsync
		msg := strings.Repeat(" ", width)
		d.wsync <- utf8.RuneCountInString(d.FormatMsg(msg))
	}()
	return ""
}