Files
conquest/src/client/views/console.nim

91 lines
4.0 KiB
Nim
Raw Normal View History

import strformat, strutils
import imguin/[cimgui, glfw_opengl, simple]
import ../utils/appImGui
import ../../common/[types]
type
ConsoleComponent* = ref object of RootObj
agent: Agent
showConsole*: bool
inputBuffer: string
consoleEntries: seq[string]
2025-09-11 19:11:11 +02:00
console: ptr TextEditor
proc Console*(agent: Agent): ConsoleComponent =
result = new ConsoleComponent
result.agent = agent
result.showConsole = true
2025-09-11 19:11:11 +02:00
result.console = TextEditor_TextEditor()
result.consoleEntries = @[
"a",
2025-09-11 19:11:11 +02:00
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
]
2025-09-11 19:11:11 +02:00
result.console.TextEditor_SetText(result.consoleEntries.join("\n") & '\0')
proc findLongestLength(text: string): float32 =
var maxWidth = 0.0f
for line in text.splitLines():
let line_cstring = line.cstring
var textSizeOut: ImVec2
igCalcTextSize(addr textSizeOut, line_cstring, nil, false, -1.0f)
if textSizeOut.x > maxWidth:
maxWidth = textSizeOut.x
return maxWidth
proc draw*(component: ConsoleComponent) =
igBegin(fmt"[{component.agent.agentId}] {component.agent.username}@{component.agent.hostname}", addr component.showConsole, 0)
defer: igEnd()
# Console text section
2025-09-11 19:11:11 +02:00
# A InputTextMultiline component is placed within a Child Frame to enable both proper text selection and a horizontal scrollbar
# The only thing missing from this implementation is the ability change the text color
# https://github.com/ocornut/imgui/issues/383#issuecomment-2080346129
let footerHeight = igGetStyle().ItemSpacing.y + igGetFrameHeightWithSpacing()
let buffer = component.consoleEntries.join("\n") & '\0'
# Push styles to hide the Child's background and scrollbar background.
igPushStyleColor_Vec4(ImGuiCol_FrameBg.int32, vec4(0.0f, 0.0f, 0.0f, 0.0f))
igPushStyleColor_Vec4(ImGuiCol_ScrollbarBg.int32, vec4(0.0f, 0.0f, 0.0f, 0.0f))
if igBeginChild_Str("##Console", vec2(-0.99f, -footerHeight), ImGuiChildFlags_NavFlattened.int32, ImGuiWindowFlags_HorizontalScrollbar.int32):
# Manually handle horizontal scrolling with the mouse wheel/touchpad
let io = igGetIO()
if io.MouseWheelH != 0:
let scroll_delta = io.MouseWheelH * igGetScrollX() * 0.5
igSetScrollX_Float(igGetScrollX() - scroll_delta)
if igGetScrollX() == 0:
igSetScrollX_Float(1.0f) # This is required to prevent the horizontal scrolling from snapping in
# Retrieve the length of the longes console entry
2025-09-11 19:11:11 +02:00
var width = findLongestLength(buffer)
if width <= io.DisplaySize.x:
width = -1.0f
# Set the Text edit background color and make it visible.
igPushStyleColor_Vec4(ImGuiCol_FrameBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
igPushStyleColor_Vec4(ImGuiCol_ScrollbarBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
discard igInputTextMultiline("##ConsoleText", buffer, cast[csize_t](buffer.len()), vec2(width, -1.0f), ImGui_InputTextFlags_ReadOnly.int32 or ImGui_InputTextFlags_AllowTabInput.int32, nil, nil)
2025-09-11 19:11:11 +02:00
# Alternative: ImGuiColorTextEdit
# component.console.TextEditor_SetReadOnlyEnabled(true)
# component.console.TextEditor_SetShowLineNumbersEnabled(false)
# component.console.TextEditor_Render("##ConsoleEntries", false, vec2(-1, -1), true)
igPopStyleColor(2)
igPopStyleColor(2)
igEndChild()
igSeparator()
# Input field
igSetNextItemWidth(-1.0f)
let inputFlags = ImGuiInputTextFlags_EnterReturnsTrue.int32 or ImGuiInputTextFlags_EscapeClearsAll.int32 or ImGuiInputTextFlags_CallbackCompletion.int32 or ImGuiInputTextFlags_CallbackHistory.int32
if igInputText("##Input", component.inputBuffer, 256, inputFlags, nil, nil):
discard
igSetItemDefaultFocus()