CodeEditor.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package giu
  2. import (
  3. "fmt"
  4. "github.com/AllenDang/imgui-go"
  5. )
  6. // LanguageDefinition represents code editor's language definition.
  7. type LanguageDefinition byte
  8. // language definitions:.
  9. const (
  10. LanguageDefinitionSQL LanguageDefinition = iota
  11. LanguageDefinitionCPP
  12. LanguageDefinitionLua
  13. LanguageDefinitionC
  14. )
  15. var _ Disposable = &codeEditorState{}
  16. type codeEditorState struct {
  17. editor imgui.TextEditor
  18. }
  19. // Dispose implements Disposable interface.
  20. func (s *codeEditorState) Dispose() {
  21. // noop
  22. }
  23. // static check if code editor implements Widget interface.
  24. var _ Widget = &CodeEditorWidget{}
  25. // CodeEditorWidget represents imgui.TextEditor.
  26. type CodeEditorWidget struct {
  27. title string
  28. width,
  29. height float32
  30. border bool
  31. }
  32. // CodeEditor creates new code editor widget.
  33. func CodeEditor() *CodeEditorWidget {
  34. return &CodeEditorWidget{
  35. title: GenAutoID("##CodeEditor"),
  36. }
  37. }
  38. // ID allows to manually set editor's ID.
  39. // It isn't necessary to use it in a normal conditions.
  40. func (ce *CodeEditorWidget) ID(id string) *CodeEditorWidget {
  41. ce.title = id
  42. return ce
  43. }
  44. // ShowWhitespaces sets if whitespaces are shown in code editor.
  45. func (ce *CodeEditorWidget) ShowWhitespaces(s bool) *CodeEditorWidget {
  46. ce.getState().editor.SetShowWhitespaces(s)
  47. return ce
  48. }
  49. // TabSize sets editor's tab size.
  50. func (ce *CodeEditorWidget) TabSize(size int) *CodeEditorWidget {
  51. ce.getState().editor.SetTabSize(size)
  52. return ce
  53. }
  54. // LanguageDefinition sets code editor language definition.
  55. func (ce *CodeEditorWidget) LanguageDefinition(definition LanguageDefinition) *CodeEditorWidget {
  56. s := ce.getState()
  57. lookup := map[LanguageDefinition]func(){
  58. LanguageDefinitionSQL: s.editor.SetLanguageDefinitionSQL,
  59. LanguageDefinitionCPP: s.editor.SetLanguageDefinitionCPP,
  60. LanguageDefinitionLua: s.editor.SetLanguageDefinitionLua,
  61. LanguageDefinitionC: s.editor.SetLanguageDefinitionC,
  62. }
  63. setter, correctDefinition := lookup[definition]
  64. if !correctDefinition {
  65. panic(fmt.Sprintf("giu/CodeEditor.go: unknown language definition %d", definition))
  66. }
  67. setter()
  68. return ce
  69. }
  70. // Text sets editor's text.
  71. func (ce *CodeEditorWidget) Text(str string) *CodeEditorWidget {
  72. ce.getState().editor.SetText(str)
  73. return ce
  74. }
  75. // ErrorMarkers sets error markers.
  76. func (ce *CodeEditorWidget) ErrorMarkers(markers imgui.ErrorMarkers) *CodeEditorWidget {
  77. ce.getState().editor.SetErrorMarkers(markers)
  78. return ce
  79. }
  80. // HandleKeyboardInputs sets if editor should handle keyboard input.
  81. func (ce *CodeEditorWidget) HandleKeyboardInputs(b bool) *CodeEditorWidget {
  82. ce.getState().editor.SetHandleKeyboardInputs(b)
  83. return ce
  84. }
  85. // Size sets editor's size.
  86. func (ce *CodeEditorWidget) Size(w, h float32) *CodeEditorWidget {
  87. ce.width, ce.height = w, h
  88. return ce
  89. }
  90. // Border sets editors borders.
  91. func (ce *CodeEditorWidget) Border(border bool) *CodeEditorWidget {
  92. ce.border = border
  93. return ce
  94. }
  95. // HasSelection returns true if some text is selected.
  96. func (ce *CodeEditorWidget) HasSelection() bool {
  97. return ce.getState().editor.HasSelection()
  98. }
  99. // GetSelectedText returns selected text.
  100. func (ce *CodeEditorWidget) GetSelectedText() string {
  101. return ce.getState().editor.GetSelectedText()
  102. }
  103. // GetText returns whole text from editor.
  104. func (ce *CodeEditorWidget) GetText() string {
  105. return ce.getState().editor.GetText()
  106. }
  107. // GetCurrentLineText returns current line.
  108. func (ce *CodeEditorWidget) GetCurrentLineText() string {
  109. return ce.getState().editor.GetCurrentLineText()
  110. }
  111. // GetCursorPos returns cursor position.
  112. // (in characters).
  113. func (ce *CodeEditorWidget) GetCursorPos() (x, y int) {
  114. return ce.getState().editor.GetCursorPos()
  115. }
  116. // GetSelectionStart returns star pos of selection.
  117. func (ce *CodeEditorWidget) GetSelectionStart() (x, y int) {
  118. return ce.getState().editor.GetSelectionStart()
  119. }
  120. // InsertText inserts the `text`.
  121. func (ce *CodeEditorWidget) InsertText(text string) {
  122. ce.getState().editor.InsertText(text)
  123. }
  124. // GetWordUnderCursor returns the word under the cursor.
  125. func (ce *CodeEditorWidget) GetWordUnderCursor() string {
  126. return ce.getState().editor.GetWordUnderCursor()
  127. }
  128. // SelectWordUnderCursor selects the word under cursor.
  129. func (ce *CodeEditorWidget) SelectWordUnderCursor() {
  130. ce.getState().editor.SelectWordUnderCursor()
  131. }
  132. // IsTextChanged returns true if the editable text was changed in the frame.
  133. func (ce *CodeEditorWidget) IsTextChanged() bool {
  134. return ce.getState().editor.IsTextChanged()
  135. }
  136. // GetScreenCursorPos returns cursor position on the screen.
  137. // (in pixels).
  138. func (ce *CodeEditorWidget) GetScreenCursorPos() (x, y int) {
  139. return ce.getState().editor.GetScreenCursorPos()
  140. }
  141. // Copy copies selection.
  142. func (ce *CodeEditorWidget) Copy() {
  143. ce.getState().editor.Copy()
  144. }
  145. // Cut cuts selection.
  146. func (ce *CodeEditorWidget) Cut() {
  147. ce.getState().editor.Cut()
  148. }
  149. // Paste does the same as Ctrl+V.
  150. func (ce *CodeEditorWidget) Paste() {
  151. ce.getState().editor.Paste()
  152. }
  153. // Delete deletes the selection.
  154. func (ce *CodeEditorWidget) Delete() {
  155. ce.getState().editor.Delete()
  156. }
  157. // Build implements Widget interface.
  158. func (ce *CodeEditorWidget) Build() {
  159. s := ce.getState()
  160. // register text in font atlas
  161. tStr(s.editor.GetText())
  162. // build editor
  163. s.editor.Render(ce.title, imgui.Vec2{X: ce.width, Y: ce.height}, ce.border)
  164. }
  165. func (ce *CodeEditorWidget) getState() (state *codeEditorState) {
  166. if s := Context.GetState(ce.title); s == nil {
  167. state = &codeEditorState{
  168. editor: imgui.NewTextEditor(),
  169. }
  170. Context.SetState(ce.title, state)
  171. } else {
  172. var isOk bool
  173. state, isOk = s.(*codeEditorState)
  174. Assert(isOk, "CodeEditorWidget", "getState", "unexpected widget's state type")
  175. }
  176. return state
  177. }