瀏覽代碼

Working Bar, fixed -1 EINTR in WaitKey.

Steve Thielemann 3 年之前
父節點
當前提交
37dafc2e29
共有 3 個文件被更改,包括 239 次插入20 次删除
  1. 9 0
      door/input.go
  2. 182 19
      door/line.go
  3. 48 1
      testdoor/testdoor.go

+ 9 - 0
door/input.go

@@ -306,7 +306,16 @@ func (d *Door) WaitKey(secs int64, usecs int64) int {
 	// timeout := syscall.Timeval{Sec: 0, Usec: 100}
 	timeout := syscall.Timeval{Sec: secs, Usec: usecs}
 	v, err := syscall.Select(d.READFD+1, &fdsetRead, nil, nil, &timeout)
+
 	if v == -1 {
+		errno, ok := err.(syscall.Errno)
+		if ok && errno == syscall.EINTR {
+			return -1
+		}
+
+		// Interrupted system call ???  What does this mean?
+		// This isn't hangup.  I'm still connected.
+		// -1 :  interrupted system call
 		fmt.Println("-1 : ", err)
 		// hangup ?!
 		return -2

+ 182 - 19
door/line.go

@@ -1,19 +1,10 @@
 package door
 
-// This was the way I did it in door++...
-// Don't
-/*
-type RenderOutput struct {
-	Color string
-	Pos   int
-	Len   int
-}
-
-type Render struct {
-	Text    string
-	Outputs []RenderOutput
-}
-*/
+import (
+	"fmt"
+	"strings"
+	"unicode"
+)
 
 type Line struct {
 	Text         string
@@ -34,12 +25,184 @@ func (l *Line) Update() bool {
 	return false
 }
 
-func (l *Line) Output(d *Door) {
+func (l *Line) Output() string {
 	if l.RenderF == nil {
-		output := l.DefaultColor + l.Text
-		d.Write(output)
+		return l.DefaultColor + l.Text
 	} else {
-		output := l.RenderF(l.Text)
-		d.Write(output)
+		return l.RenderF(l.Text)
 	}
 }
+
+// Sample RenderF function
+// Upcase is BOLD Blue, everything else is Yellow
+func RenderBlueYellow(text string) string {
+	var output string
+	var lastColor string
+
+	blue := ColorText("BOLD BLUE")
+	yellow := ColorText("BOLD YELLOW")
+
+	for _, letter := range text {
+		if unicode.IsUpper(letter) {
+			if lastColor != blue {
+				lastColor = blue
+				output += blue
+			}
+			output += string(letter)
+		} else {
+			if lastColor != yellow {
+				lastColor = yellow
+				output += yellow
+			}
+			output += string(letter)
+		}
+	}
+	return output
+}
+
+type BarStyle int
+
+const (
+	SOLID BarStyle = iota
+	HALF_STEP
+	GRADIENT
+	PERCENTAGE
+	PERCENT_SPACE
+)
+
+type BarRange struct {
+	Percent int64
+	Color   string
+}
+
+type BarLine struct {
+	Width      int
+	Style      BarStyle
+	Percent    int64 // percentage * 100
+	ColorRange []BarRange
+	UpdateP    func() int64
+	Line
+}
+
+func (bl *BarLine) CheckRange() {
+	if len(bl.ColorRange) != 0 {
+		// Ok, there is a color range.  Get checking
+
+		for _, br := range bl.ColorRange {
+			if bl.Percent <= br.Percent {
+				bl.DefaultColor = br.Color
+				break
+			}
+		}
+	}
+}
+
+func (bl *BarLine) Output() string {
+	var output string
+	var step_width int64
+
+	if bl.UpdateP != nil {
+		bl.Percent = bl.UpdateP()
+	}
+
+	bl.CheckRange()
+
+	switch bl.Style {
+	case SOLID, PERCENTAGE, PERCENT_SPACE:
+		step_width = int64(100 * 100 / bl.Width)
+		var steps int = int(bl.Percent / step_width)
+
+		if Unicode {
+			output += strings.Repeat("\u2588", steps)
+		} else {
+			output += strings.Repeat("\xdb", steps)
+		}
+		// This will work, because we aren't trying to len(output) with unicode.
+		output += strings.Repeat(" ", int(bl.Width-steps))
+
+		if bl.Style == PERCENTAGE || bl.Style == PERCENT_SPACE {
+			percent := fmt.Sprintf("%d", bl.Percent/100)
+
+			var pos int = bl.Width/2 - 1
+			if percent != "100" {
+				percent += "%"
+				if len(percent) < 3 {
+					percent = " " + percent
+				}
+			}
+
+			if bl.Style == PERCENT_SPACE {
+				percent = " " + percent + " "
+				pos--
+			}
+			// to process/slice the string (with unicode) do this:
+			// convert to []rune, slice that, convert back to string
+			//
+			// sliceable := []rune(output)
+			// newString := string(sliceable[:5]) + " new content " + (sliceable[10:])
+			// fmt.Printf("%d %d [%s] %d [%s]\n", bl.Width, pos, percent, len(output), output)
+
+			if Unicode {
+				runes := []rune(output)
+				output = string(runes[:pos]) + percent + string(runes[pos+len(percent):])
+			} else {
+				output = output[:pos] + percent + output[pos+len(percent):]
+			}
+		}
+	case HALF_STEP:
+		step_width = int64(100 * 100 / bl.Width)
+		var steps int = int(bl.Percent * 2 / step_width)
+
+		if Unicode {
+			output += strings.Repeat("\u2588", steps/2)
+		} else {
+			output += strings.Repeat("\xdb", steps/2)
+		}
+		if steps%1 == 1 {
+			if Unicode {
+				output += "\u258c"
+			} else {
+				output += "\xdd"
+			}
+			steps++
+		}
+		output += strings.Repeat(" ", bl.Width-(steps/2))
+
+	case GRADIENT:
+		step_width = int64(100 * 100 / bl.Width)
+		var steps int = int(bl.Percent * 4 / step_width)
+		if Unicode {
+			output += strings.Repeat("\u2588", steps/4)
+		} else {
+			output += strings.Repeat("\xb0", steps/4)
+		}
+		if steps%4 != 0 {
+			switch steps % 4 {
+			case 1:
+				if Unicode {
+					output += "\u2591"
+				} else {
+					output += "\xb0"
+				}
+			case 2:
+				if Unicode {
+					output += "\u2592"
+				} else {
+					output += "\xb1"
+				}
+			case 3:
+				if Unicode {
+					output += "\u2593"
+				} else {
+					output += "\xb2"
+				}
+			}
+			for steps%4 != 0 {
+				steps++
+			}
+		}
+		output += strings.Repeat(" ", bl.Width-(steps/4))
+	}
+
+	return bl.DefaultColor + output
+}

+ 48 - 1
testdoor/testdoor.go

@@ -5,6 +5,12 @@ import (
 	"red-green/door"
 )
 
+func pctUpdate(pct *int64) func() int64 {
+	return func() int64 {
+		return *pct
+	}
+}
+
 func main() {
 	fmt.Println("Starting testdoor.go")
 	d := door.Door{}
@@ -33,10 +39,51 @@ func main() {
 	d.Write(message)
 
 	inputColor := door.ColorText("BRI WHI ON BLUE")
-	d.Write("What is your name: " + inputColor)
+
+	prompt := door.Line{Text: "What is YOUR Name: "}
+	prompt.RenderF = door.RenderBlueYellow
+	d.Write(prompt.Output() + inputColor)
+	// d.Write("What is your name: " + inputColor)
 	name := d.Input(25)
 	d.Write(door.Reset + door.CRNL)
 
+	bar := door.BarLine{Line: door.Line{DefaultColor: door.ColorText("BOLD YELLOW")}, Width: 20, Style: door.HALF_STEP}
+
+	bar2 := door.BarLine{Width: 30, Style: door.PERCENT_SPACE}
+
+	bar2.ColorRange = []door.BarRange{
+		{2500, door.ColorText("RED")},
+		{5000, door.ColorText("BROWN")},
+		{7500, door.ColorText("BOLD YEL")},
+		{9500, door.ColorText("GREEN")},
+		{10100, door.ColorText("BRI GRE")}}
+
+	bar3 := door.BarLine{Width: 15, Style: door.GRADIENT, Line: door.Line{DefaultColor: door.ColorText("CYAN")}}
+
+	var percentage int64
+	bar.UpdateP = pctUpdate(&percentage)
+	bar2.UpdateP = pctUpdate(&percentage)
+	bar3.UpdateP = pctUpdate(&percentage)
+
+	bar_start := door.Goto(3, 15)
+
+	for f := 0; f <= 100; f++ {
+		percentage = int64(f * 100)
+		d.Write(bar_start)
+		bar.Update()
+		d.Write(bar.Output())
+		d.Write("  " + door.Reset)
+		bar2.Update()
+		d.Write(bar2.Output())
+		d.Write(door.Reset + "  ")
+		bar3.Update()
+		d.Write(bar3.Output())
+
+		d.WaitKey(0, 55000)
+	}
+
+	d.Write(door.CRNL)
+
 	message = fmt.Sprintf("Returning %s to the BBS..."+door.CRNL, name)
 	d.Write(message)