summaryrefslogtreecommitdiff
path: root/structs.go
blob: 6c6ca456fdf4429f3270093d827edab810f8e3ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
// Use of this source code is governed by the GPL 3.0

// all structures and variables are local (aka lowercase)
// since the plugin should be isolated to access only
// by functions() to insure everything here is run
// inside a dedicated goroutine

package main

import (
	"fmt"
	"reflect"
	"strconv"
	"sync"

	"github.com/awesome-gocui/gocui"

	log "go.wit.com/log"
	"go.wit.com/toolkits/tree"
)

// It's probably a terrible idea to call this 'me'
// 2025 note: doesn't seem terrible to call this 'me' anymore. notsure.
var me config

// todo: move all this to a protobuf. then, redo all this mess.
// it got me here, but now it's time to clean it up for good
// I can't get a GO plugins that use protobuf to load yet (versioning mismatch)
type config struct {
	baseGui          *gocui.Gui      // the main gocui handle
	treeRoot         *tree.Node      // the base of the binary tree. it should have id == 0
	myTree           *tree.TreeInfo  // ?
	ctrlDown         *tree.Node      // shown if you click the mouse when the ctrl key is pressed
	currentWindow    *guiWidget      // this is the current tab or window to show
	helpLabel        *gocui.View     // ?
	showHelp         bool            // toggle boolean for the help menu (deprecate?)
	FramePadW        int             `default:"1" dense:"0"` // When the widget has a frame, like a button, it adds 2 lines runes on each side
	FramePadH        int             `default:"1" dense:"0"` // When the widget has a frame, like a button, it adds 2 lines runes on each side
	PadW             int             `default:"1" dense:"0"` // pad spacing
	PadH             int             `default:"1" dense:"0"` // pad spacing
	WindowW          int             `default:"8" dense:"0"` // how far down to start Window or Tab headings
	WindowH          int             `default:"-1"`          // how far down to start Window or Tab headings
	TabW             int             `default:"5" dense:"0"` // how far down to start Window or Tab headings
	TabH             int             `default:"1" dense:"0"` // how far down to start Window or Tab headings
	WindowPadW       int             `default:"8" dense:"0"` // additional amount of space to put between window & tab widgets
	TabPadW          int             `default:"4" dense:"0"` // additional amount of space to put between window & tab widgets
	GroupPadW        int             `default:"2" dense:"1"` // additional amount of space to indent on a group
	BoxPadW          int             `default:"2" dense:"1"` // additional amount of space to indent on a box
	GridPadW         int             `default:"2" dense:"1"` // additional amount of space to indent on a grid
	RawW             int             `default:"1"`           // the raw beginning of each window (or tab)
	RawH             int             `default:"5"`           // the raw beginning of each window (or tab)
	FakeW            int             `default:"20"`          // offset for the hidden widgets
	padded           bool            // add space between things like buttons
	bookshelf        bool            // do you want things arranged in the box like a bookshelf or a stack?
	canvas           bool            // if set to true, the windows are a raw canvas
	menubar          bool            // for windows
	stretchy         bool            // expand things like buttons to the maximum size
	margin           bool            // add space around the frames of windows
	writeMutex       sync.Mutex      // writeMutex protects writes to *guiWidget (it's global right now maybe)
	ecount           int             // counts how many mouse and keyboard events have occurred
	supermouse       bool            // prints out every widget found while you move the mouse around
	depth            int             // used for listWidgets() debugging
	globalMouseDown  bool            // yep, mouse is pressed
	newWindowTrigger chan *guiWidget // work around hack to redraw windows a bit after NewWindow()
	stdout           stdout          // information for the STDOUT window
	showDebug        bool            // todo: move this into config struct
	dropdown         dropdown        // the dropdown menu
	textbox          dropdown        // the textbox popup window
	allwin           []*guiWidget    // for tracking which window is next
	downW            int             // where the mouse was pressed down
	downH            int             // where the mouse was pressed down
	currentDrag      *guiWidget      // what widget is currently being moved around
	dark             bool            // use a 'dark' color palette
}

// settings for the stdout window
type stdout struct {
	tk              *guiWidget // where to show STDOUT
	w               int        // the width
	h               int        // the height
	outputOnTop     bool       // is the STDOUT window on top?
	outputOffscreen bool       // is the STDOUT window offscreen?
	lastW           int        // the last 'w' location (used to move from offscreen to onscreen)
	lastH           int        // the last 'h' location (used to move from offscreen to onscreen)
	mouseOffsetW    int        // the current 'w' offset
	mouseOffsetH    int        // the current 'h' offset
	init            bool       // moves the window offscreen on startup
	resize          bool       // user is resizing the window
	outputS         []string   // the buffer of all the output
	pager           int        // allows the user to page through the buffer
}

// settings for the dropdown window
type dropdown struct {
	tk       *guiWidget // where to show STDOUT
	callerTK *guiWidget // which widget called the dropdown menu
	items    []string   // what is currently in the menu
	w        int        // the width
	h        int        // the height
	active   bool       // is the dropdown menu currently in use?
	init     bool       // moves the window offscreen on startup
	wId      int        // the widget id to use
	// dtoggle bool       // is a dropdown or combobox currently active?
}

// this is the gocui way
// corner starts at in the upper left corner
type rectType struct {
	w0, h0, w1, h1 int // left top right bottom
}

func (r *rectType) Width() int {
	return r.w1 - r.w0
}

func (r *rectType) Height() int {
	return r.h1 - r.h0
}

// settings that are window specific
type window struct {
	windowFrame *guiWidget // this is the frame for a window widget
	wasDragged  bool       // indicates the window was dragged. This keeps it from being rearranged
	dragW       int        // when dragging a window, this is the offset to the mouse position
	dragH       int        // when dragging a window, this is the offset to the mouse position
	hasTabs     bool       // does the window have tabs?
	currentTab  bool       // the visible tab
	selectedTab *tree.Node // for a window, this is currently selected tab
	active      bool       // means this window is the active one
	isBG        bool       // means this is the background widget. There is only one of these
	order       int        // what level the window is on
	resize      bool       // only set the title once
	collapsed   bool       // only show the window title bar
	dense       bool       // true if the window is huge
}

type colorT struct {
	frame gocui.Attribute
	fg    gocui.Attribute
	bg    gocui.Attribute
	selFg gocui.Attribute
	selBg gocui.Attribute
	name  string
}

type guiWidget struct {
	v            *gocui.View  // this is nil if the widget is not displayed
	cuiName      string       // what gocui uses to reference the widget (usually "TK <widgetId>"
	parent       *guiWidget   // mirrors the binary node tree
	children     []*guiWidget // mirrors the binary node tree
	node         *tree.Node   // the pointer back to the tree
	windowFrame  *guiWidget   // this is the frame for a window widget
	internal     bool         // indicates the widget is internal to gocui and should be treated differently
	dragW        int          // when dragging a window, this is the offset to the mouse position
	dragH        int          // when dragging a window, this is the offset to the mouse position
	hasTabs      bool         // does the window have tabs?
	currentTab   bool         // the visible tab
	window       window       // holds information specific only to Window widgets
	value        string       // ?
	checked      bool         // ?
	labelN       string       // the actual text to display in the console
	vals         []string     // dropdown menu items
	enable       bool         // ?
	gocuiSize    rectType     // should mirror the real display size. todo: verify these are accurate. they are not yet
	full         rectType     // full size of children (used by widget.Window, etc)
	force        rectType     // force widget within these boundries (using this to debug window dragging)
	startW       int          // ?
	startH       int          // ?
	isFake       bool         // widget types like 'box' are 'false'
	widths       map[int]int  // how tall each row in the grid is
	heights      map[int]int  // how wide each column in the grid is
	tainted      bool         // ?
	frame        bool         // ?
	selectedTab  *tree.Node   // for a window, this is currently selected tab
	color        *colorT      // what color to use
	defaultColor *colorT      // the default colors // TODO: make a function for this instead
	isBG         bool         // means this is the background widget. There is only one of these
	// resize       bool         // the window is currently being resized
}

// THIS IS GO COMPILER MAGIC
// this sets the `default` in the structs above on init()
// this is cool code. thank the GO devs for this code and Alex Flint for explaining it to me
func Set(ptr interface{}, tag string) error {
	if reflect.TypeOf(ptr).Kind() != reflect.Ptr {
		log.Log(ERROR, "Set() Not a pointer", ptr, "with tag =", tag)
		return fmt.Errorf("Not a pointer")
	}

	v := reflect.ValueOf(ptr).Elem()
	t := v.Type()

	for i := 0; i < t.NumField(); i++ {
		defaultVal := t.Field(i).Tag.Get(tag)
		name := t.Field(i).Name
		// log("Set() try name =", name, "defaultVal =", defaultVal)
		setField(v.Field(i), defaultVal, name)
	}
	return nil
}

func setField(field reflect.Value, defaultVal string, name string) error {

	if !field.CanSet() {
		// log("setField() Can't set value", field, defaultVal)
		return fmt.Errorf("Can't set value\n")
	} else {
		log.Log(NOW, "setField() Can set value", name, defaultVal)
	}

	switch field.Kind() {
	case reflect.Int:
		val, _ := strconv.Atoi(defaultVal)
		field.Set(reflect.ValueOf(int(val)).Convert(field.Type()))
	case reflect.String:
		field.Set(reflect.ValueOf(defaultVal).Convert(field.Type()))
	case reflect.Bool:
		if defaultVal == "true" {
			field.Set(reflect.ValueOf(true))
		} else {
			field.Set(reflect.ValueOf(false))
		}
	}

	return nil
}