closes #38 - only vital panic calls are remained

This commit is contained in:
Vladimir Markelov 2015-12-08 16:25:31 -08:00
parent 2b10c92a2f
commit a225b5047b
8 changed files with 80 additions and 53 deletions

View File

@ -1,7 +1,6 @@
package clui
import (
"fmt"
xs "github.com/huandu/xstrings"
term "github.com/nsf/termbox-go"
)
@ -18,8 +17,11 @@ type FrameBuffer struct {
// NewFrameBuffer creates new buffer. Width and height of a new buffer cannot be less than 3
func NewFrameBuffer(w, h int) *FrameBuffer {
if w < 3 || h < 3 {
panic(fmt.Sprintf("Invalid size: %vx%v.", w, h))
if w < 3 {
w = 3
}
if h < 3 {
h = 3
}
c := new(FrameBuffer)
@ -39,12 +41,15 @@ FrameBuffer is recreated and cleared with default colors. Both FrameBuffer width
height must be greater than 2
*/
func (fb *FrameBuffer) SetSize(w, h int) {
if w == fb.w && h == fb.h {
return
if w < 3 {
w = 3
}
if h < 3 {
h = 3
}
if w < 3 || h < 3 {
panic(fmt.Sprintf("Invalid size: %vx%v.", w, h))
if w == fb.w && h == fb.h {
return
}
fb.w, fb.h = w, h
@ -223,15 +228,11 @@ func (fb *FrameBuffer) DrawFrame(x, y, w, h int, fg, bg term.Attribute, frameCha
return
}
if frameChars == "" {
if xs.Len(frameChars) < 6 {
frameChars = "─│┌┐└┘"
}
parts := []rune(frameChars)
if len(parts) < 6 {
panic("Invalid theme: single border")
}
H, V, UL, UR, DL, DR := parts[0], parts[1], parts[2], parts[3], parts[4], parts[5]
if h == 1 {

View File

@ -36,11 +36,12 @@ func (c *Composer) initBuffer() {
c.canvas.Clear(ColorBlack)
}
// InitLibrary initializes library and starts console management
// InitLibrary initializes library and starts console management.
// Retuns nil in case of error
func InitLibrary() *Composer {
err := term.Init()
if err != nil {
panic(err)
return nil
}
c := new(Composer)
@ -128,13 +129,13 @@ func (c *Composer) checkWindowUnderMouse(screenX, screenY int) (View, HitResult)
return nil, HitOutside
}
func (c *Composer) activateView(view View) {
func (c *Composer) activateView(view View) bool {
if c.topView() == view {
for _, v := range c.views {
v.SetActive(false)
}
view.SetActive(true)
return
return true
}
var wList []View
@ -150,11 +151,12 @@ func (c *Composer) activateView(view View) {
}
if !found {
panic("Invalid view to activate")
return false
}
view.SetActive(true)
c.views = append(wList, view)
return true
}
func (c *Composer) moveActiveWindowToBottom() bool {
@ -176,7 +178,9 @@ func (c *Composer) moveActiveWindowToBottom() bool {
}
c.views[0] = last
c.activateView(c.topView())
if !c.activateView(c.topView()) {
return false
}
event = Event{Type: EventActivate, X: 1} // send 'activated'
c.sendEventToActiveView(event)

View File

@ -1,7 +1,6 @@
package clui
import (
"fmt"
term "github.com/nsf/termbox-go"
"log"
)
@ -46,13 +45,22 @@ func (c *ControlBase) Size() (int, int) {
// SetSize changes control size. Constant DoNotChange can be
// used as placeholder to indicate that the control attrubute
// should be unchanged.
// Method panics if new size is less than minimal size
func (c *ControlBase) SetSize(width, height int) {
if width != DoNotChange && (width > 1000 || width < c.minW) {
panic(fmt.Sprintf("Invalid width: %v", width))
if width != DoNotChange {
if width > 1000 {
width = 1000
}
if width < c.minW {
width = c.minW
}
}
if height != DoNotChange && (height > 200 || height < c.minH) {
panic(fmt.Sprintf("Invalid height: %v", height))
if height != DoNotChange {
if height > 200 {
height = 200
}
if height < c.minH {
height = c.minH
}
}
if width != DoNotChange {

View File

@ -151,11 +151,13 @@ func (d *ConfirmationDialog) Result() int {
// selectedItem is the index of the item that is selected after
// the dialog is created
// typ is a selection type: ListBox or RadioGroup
// Returns nil in case of creation process fails, e.g, if item list is empty
func NewSelectDialog(c *Composer, title string, items []string, selectedItem int, typ SelectDialogType) *SelectDialog {
dlg := new(SelectDialog)
if len(items) == 0 {
panic("Item list must contain at least 1 item")
// Item list must contain at least 1 item
return nil
}
cw, ch := term.Size()

View File

@ -119,7 +119,8 @@ func (f *Frame) RecalculateConstraints() {
// its minimal size
func (f *Frame) AddChild(c Control, scale int) {
if f.view.ChildExists(c) {
panic("Frame: Cannot add the same control twice")
// Frame: Cannot add the same control twice
return
}
c.SetScale(scale)
@ -135,10 +136,11 @@ func (f *Frame) Children() []Control {
// SetPack changes the direction of children packing.
// Changing pack type on the fly is not always possible:
// it panics if a frame already contains children
// it does nothing if a frame already contains children
func (f *Frame) SetPack(pk PackType) {
if len(f.children) > 0 {
panic("Control already has children")
// Control already has children
return
}
f.pack = pk

View File

@ -104,7 +104,6 @@ type View interface {
// SetSize changes control size. Constant DoNotChange can be
// used as placeholder to indicate that the control attrubute
// should be unchanged.
// Method panics if new size is less than minimal size
SetSize(int, int)
// Pos returns the current control position: X and Y.
// For View the position's origin is top left corner of console window,
@ -173,7 +172,7 @@ type View interface {
SetPaddings(int, int, int, int)
// AddChild add control to a list of view children. Minimal size
// of the view calculated as a sum of sizes of its children.
// Method panics if the same control is added twice
// Method does nothing if the control is already added
AddChild(Control, int)
// SetPack changes the direction of children packing
SetPack(PackType)
@ -251,7 +250,6 @@ type Control interface {
// SetSize changes control size. Constant DoNotChange can be
// used as placeholder to indicate that the control attrubute
// should be unchanged.
// Method panics if new size is less than minimal size
SetSize(int, int)
// Scale return scale coefficient that is used to calculate
// new control size after its parent resizes.

View File

@ -40,8 +40,8 @@ Theme file is a simple text file that has similar to INI file format:
6. Non-system keys are divided into two groups: Colors and Objects
Colors are the keys that end with 'Back' or 'Text' - background
and text color, respectively. If theme manager cannot
value to color it panics. See Color*Back * Color*Text constants,
just drop 'Color' at the beginning of key name.
value to color it uses black color. See Color*Back * Color*Text
constants, just drop 'Color' at the beginning of key name.
Rules of converting text to color:
1. If the value does not end neither with 'Back' nor with 'Text'
it is considered as raw attribute value(e.g, 'green bold')
@ -60,9 +60,10 @@ Theme file is a simple text file that has similar to INI file format:
Better way is:
Viewback=parent.ViewText
ViewText=parent.ViewBack
Converting text to real color panics if a) the string does not look
like real color(e.g, typo as in 'grean bold'), b) parent theme
has not loaded yet, c) parent theme does not have the color
Converting text to real color fails and retuns black color if
a) the string does not look like real color(e.g, typo as in
'grean bold'), b) parent theme has not loaded yet, c) parent
theme does not have the color
with the same name
Other keys are considered as objects - see Obj* constants, just drop
'Obj' at the beginning of the key name
@ -180,7 +181,9 @@ func (s *ThemeManager) Reset() {
s.themes[defaultTheme] = defTheme
}
// SysColor returns attribute by its id for the current theme
// SysColor returns attribute by its id for the current theme.
// The method panics if theme loop is detected - check if
// parent attribute is correct
func (s *ThemeManager) SysColor(color string) term.Attribute {
sch, ok := s.themes[s.current]
if !ok {
@ -216,7 +219,9 @@ func (s *ThemeManager) SysColor(color string) term.Attribute {
}
// SysObject returns object look by its id for the current
// theme. E.g, border lines for frame or arrows for scrollbar
// theme. E.g, border lines for frame or arrows for scrollbar.
// The method panics if theme loop is detected - check if
// parent attribute is correct
func (s *ThemeManager) SysObject(object string) string {
sch, ok := s.themes[s.current]
if !ok {

View File

@ -1,7 +1,6 @@
package clui
import (
"fmt"
term "github.com/nsf/termbox-go"
"log"
)
@ -62,18 +61,27 @@ func NewWindow(parent Screen, x, y, w, h int, title string) *Window {
// SetSize changes control size. Constant DoNotChange can be
// used as placeholder to indicate that the control attrubute
// should be unchanged.
// Method panics if new size is less than minimal size.
// View automatically recalculates position and size of its children after changing its size
func (w *Window) SetSize(width, height int) {
if width == w.width && height == w.height {
return
}
if width != DoNotChange && (width > 1000 || width < w.minW) {
panic(fmt.Sprintf("Invalid width: %v", width))
if width != DoNotChange {
if width > 1000 {
width = 1000
}
if width < w.minW {
width = w.minW
}
}
if height != DoNotChange && (height > 200 || height < w.minH) {
panic(fmt.Sprintf("Invalid height: %v", height))
if height != DoNotChange {
if height > 200 {
height = 200
}
if height < w.minH {
height = w.minH
}
}
if width != DoNotChange {
@ -120,16 +128,14 @@ func (w *Window) SetConstraints(width, height int) {
}
// Draw paints the view screen buffer to a canvas. It does not
// repaint all view children
// repaint all view children.
// Method does nothing if coordinates are outside canvas
func (w *Window) Draw(canvas Canvas) {
for y := 0; y < w.height; y++ {
for x := 0; x < w.width; x++ {
s, ok := w.canvas.Symbol(x, y)
if ok {
canvas.PutSymbol(x+w.x, y+w.y, s)
} else {
wx, wy := w.Size()
panic(fmt.Sprintf("Invalid x, y: %vx%v of %vx%v", x, y, wx, wy))
}
}
}
@ -242,11 +248,12 @@ func (w *Window) Buttons() ViewButton {
return w.buttons
}
// SetPack changes the direction of children packing. Call the method only before any child is added to view. Otherwise, the method
// panics if a view already contains children
// SetPack changes the direction of children packing. Call the method
// only before any child is added to view. Otherwise, the method
// does nothing
func (w *Window) SetPack(pk PackType) {
if len(w.children) > 0 {
panic("Control already has children")
return
}
w.pack = pk
@ -289,10 +296,10 @@ func (w *Window) RegisterControl(c Control) {
// AddChild add control to a list of view children. Minimal size
// of the view calculated as a sum of sizes of its children.
// Method panics if the same control is added twice
// Method does nothing if the control is already added
func (w *Window) AddChild(c Control, scale int) {
if w.ChildExists(c) {
panic("Cannot add the same control twice")
return
}
c.SetScale(scale)