Implemented multi-select functionality and basic context-menu for session table.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[Window][Dockspace]
|
||||
Pos=0,0
|
||||
Size=1908,999
|
||||
Size=2548,1359
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
@@ -9,26 +9,26 @@ Size=449,261
|
||||
Collapsed=0
|
||||
|
||||
[Window][Dear ImGui Demo]
|
||||
Pos=10,43
|
||||
Size=1453,946
|
||||
Pos=1852,43
|
||||
Size=686,653
|
||||
Collapsed=0
|
||||
DockId=0x00000001,1
|
||||
DockId=0x00000007,0
|
||||
|
||||
[Window][Agents [Table View]]
|
||||
Pos=10,43
|
||||
Size=1187,946
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Agents [Graph View]]
|
||||
Pos=10,43
|
||||
Size=1888,473
|
||||
Collapsed=0
|
||||
DockId=0x00000001,1
|
||||
DockId=0x00000006,1
|
||||
|
||||
[Window][Eventlog]
|
||||
Pos=1465,43
|
||||
Size=433,946
|
||||
Pos=10,698
|
||||
Size=2528,651
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
@@ -48,9 +48,10 @@ Size=1150,550
|
||||
Collapsed=0
|
||||
|
||||
[Window][Dear ImGui Debug Log]
|
||||
Pos=60,60
|
||||
Size=1088,486
|
||||
Pos=10,698
|
||||
Size=2528,651
|
||||
Collapsed=0
|
||||
DockId=0x00000004,1
|
||||
|
||||
[Window][Dear ImGui Metrics/Debugger]
|
||||
Pos=60,60
|
||||
@@ -59,9 +60,9 @@ Collapsed=0
|
||||
|
||||
[Window][Sessions [Table View]]
|
||||
Pos=10,43
|
||||
Size=1453,946
|
||||
Size=1840,653
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Dear ImGui Demo/ResizableChild_478B81A3]
|
||||
IsChild=1
|
||||
@@ -93,6 +94,10 @@ Size=1453,471
|
||||
Collapsed=0
|
||||
DockId=0x00000002,0
|
||||
|
||||
[Window][Dear ImGui Demo/##Basket_87771727]
|
||||
IsChild=1
|
||||
Size=614,540
|
||||
|
||||
[Table][0xB6880529,2]
|
||||
RefScale=27
|
||||
Column 0 Sort=0v
|
||||
@@ -100,21 +105,21 @@ Column 0 Sort=0v
|
||||
[Table][0x951FCC8A,6]
|
||||
RefScale=27
|
||||
Column 0 Width=48
|
||||
Column 1 Width=72 Sort=0v
|
||||
Column 1 Width=112 Sort=0v
|
||||
Column 2 Width=108
|
||||
Column 3 Weight=0.5480
|
||||
Column 3 Width=136
|
||||
Column 4 Weight=1.0000
|
||||
Column 5 Weight=-1.0000
|
||||
Column 5 Width=-1
|
||||
|
||||
[Table][0x32886A44,8]
|
||||
Column 0 Weight=0.7758
|
||||
Column 1 Weight=1.1556
|
||||
Column 2 Weight=0.7758
|
||||
Column 3 Weight=0.9616
|
||||
Column 4 Weight=0.9616
|
||||
Column 5 Weight=1.1556
|
||||
Column 6 Weight=0.3879
|
||||
Column 7 Weight=1.8263
|
||||
Column 0 Weight=0.7126
|
||||
Column 1 Weight=1.0615
|
||||
Column 2 Weight=0.7126
|
||||
Column 3 Weight=1.2397
|
||||
Column 4 Weight=1.6776
|
||||
Column 5 Weight=1.2397
|
||||
Column 6 Weight=0.3563
|
||||
Column 7 Weight=1.5466
|
||||
|
||||
[Table][0x51D6F5EA,3]
|
||||
Column 0 Weight=1.0000
|
||||
@@ -168,9 +173,9 @@ Column 1 Weight=1.0000
|
||||
|
||||
[Table][0xAED4F161,3]
|
||||
RefScale=27
|
||||
Column 0 Width=191 Visible=1
|
||||
Column 1 Width=108 Visible=1 Sort=0v
|
||||
Column 2 Width=-1 Visible=0
|
||||
Column 0 Weight=1.0000
|
||||
Column 1 Width=839 Sort=0v
|
||||
Column 2 Width=-1
|
||||
|
||||
[Table][0x3A20F3F3,3]
|
||||
RefScale=27
|
||||
@@ -182,7 +187,7 @@ Column 2 Width=96
|
||||
|
||||
[Table][0x302651AD,14]
|
||||
RefScale=27
|
||||
Column 0 Width=96 Sort=0v
|
||||
Column 0 Width=96
|
||||
Column 1 Width=33
|
||||
Column 2 Width=33
|
||||
Column 3 Width=33
|
||||
@@ -222,13 +227,13 @@ Column 2 Weight=1.0000
|
||||
|
||||
[Table][0x127BEAD2,7]
|
||||
RefScale=27
|
||||
Column 0 Width=84
|
||||
Column 1 Width=167
|
||||
Column 2 Width=191
|
||||
Column 3 Width=191
|
||||
Column 4 Width=191
|
||||
Column 5 Width=191
|
||||
Column 6 Width=191
|
||||
Column 0 Width=155
|
||||
Column 1 Width=155
|
||||
Column 2 Width=155
|
||||
Column 3 Width=156
|
||||
Column 4 Width=156
|
||||
Column 5 Width=156
|
||||
Column 6 Width=474
|
||||
|
||||
[Table][0x755BE644,3]
|
||||
RefScale=27
|
||||
@@ -237,9 +242,10 @@ Column 1 Width=83
|
||||
Column 2 Width=84
|
||||
|
||||
[Table][0xBE0D9DE1,3]
|
||||
Column 0 Weight=1.0000
|
||||
Column 1 Weight=1.0000
|
||||
Column 2 Weight=1.0000
|
||||
RefScale=27
|
||||
Column 0 Width=84
|
||||
Column 1 Width=84
|
||||
Column 2 Width=217
|
||||
|
||||
[Table][0xDE11CCC7,8]
|
||||
Column 0 Weight=0.7758
|
||||
@@ -251,10 +257,18 @@ Column 5 Weight=1.1556
|
||||
Column 6 Weight=0.3879
|
||||
Column 7 Weight=1.8263
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=1888,946 Split=X
|
||||
DockNode ID=0x00000003 Parent=0x85940918 SizeRef=1453,473 Split=Y Selected=0x61E02D75
|
||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1453,473 CentralNode=1 Selected=0x61E02D75
|
||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1453,471 Selected=0x6D7E7D39
|
||||
DockNode ID=0x00000004 Parent=0x85940918 SizeRef=433,473 Selected=0x0FA43D88
|
||||
[Table][0x61294EC1,3]
|
||||
RefScale=27
|
||||
Column 0 Width=119
|
||||
Column 1 Width=119
|
||||
Column 2 Width=119
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2528,1306 Split=Y
|
||||
DockNode ID=0x00000001 Parent=0x85940918 SizeRef=1453,473 Split=Y Selected=0x61E02D75
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=2528,653 Split=X Selected=0x61E02D75
|
||||
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=1840,653 CentralNode=1 Selected=0x61E02D75
|
||||
DockNode ID=0x00000007 Parent=0x00000003 SizeRef=686,653 Selected=0x5E5F7166
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=2528,651 Selected=0x0FA43D88
|
||||
DockNode ID=0x00000002 Parent=0x85940918 SizeRef=1453,471 Selected=0x6D7E7D39
|
||||
|
||||
|
||||
@@ -19,6 +19,15 @@ proc main() =
|
||||
views["Listeners"] = addr showListeners
|
||||
views["Eventlog"] = addr showEventlog
|
||||
|
||||
# Create components
|
||||
var
|
||||
dockspace = Dockspace()
|
||||
sessionsTable = SessionsTable("Sessions [Table View]")
|
||||
sessionsGraph = SessionsTable("Sessions [Graph View]")
|
||||
listenersTable = ListenersTable("Listeners")
|
||||
eventlog = Eventlog("Eventlog")
|
||||
|
||||
|
||||
let io = igGetIO()
|
||||
|
||||
# main loop
|
||||
@@ -30,13 +39,11 @@ proc main() =
|
||||
continue
|
||||
newFrame()
|
||||
|
||||
# UI components/views
|
||||
Dockspace().draw(addr showConquest, views)
|
||||
|
||||
if showSessionsTable: SessionsTable("Sessions [Table View]").draw(addr showSessionsTable)
|
||||
if showSessionsGraph: SessionsTable("Sessions [Graph View]").draw(addr showSessionsGraph)
|
||||
if showListeners: ListenersTable("Listeners").draw(addr showListeners)
|
||||
if showEventlog:Eventlog("Eventlog").draw(addr showEventlog)
|
||||
# Draw/update UI components/views
|
||||
dockspace.draw(addr showConquest, views)
|
||||
if showSessionsTable: sessionsTable.draw(addr showSessionsTable)
|
||||
if showListeners: listenersTable.draw(addr showListeners)
|
||||
if showEventlog: eventlog.draw(addr showEventlog)
|
||||
|
||||
igShowDemoWindow(nil)
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import times
|
||||
import imguin/[cimgui, glfw_opengl, simple]
|
||||
import ../utils/appImGui
|
||||
import ../../common/[types]
|
||||
import ../../common/[types, utils]
|
||||
|
||||
type
|
||||
SessionsTableComponent = ref object of RootObj
|
||||
title: string
|
||||
agents: seq[Agent]
|
||||
|
||||
selection: ptr ImGuiSelectionBasicStorage
|
||||
|
||||
let exampleAgents: seq[Agent] = @[
|
||||
Agent(
|
||||
@@ -43,6 +43,40 @@ let exampleAgents: seq[Agent] = @[
|
||||
firstCheckin: now() - initDuration(hours = 1, minutes = 30),
|
||||
latestCheckin: now() - initDuration(minutes = 5),
|
||||
sessionKey: [byte 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
|
||||
),
|
||||
Agent(
|
||||
agentId: "C9D8E7F6",
|
||||
listenerId: "L2468135",
|
||||
username: "charlie",
|
||||
hostname: "SERVER-03",
|
||||
domain: "IT",
|
||||
ip: "172.16.0.20",
|
||||
os: "Windows Server 2019",
|
||||
process: "powershell.exe",
|
||||
pid: 7890,
|
||||
elevated: true,
|
||||
sleep: 30,
|
||||
tasks: @[],
|
||||
firstCheckin: now() - initDuration(hours = 3, minutes = 15),
|
||||
latestCheckin: now() - initDuration(minutes = 10),
|
||||
sessionKey: [byte 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
),
|
||||
Agent(
|
||||
agentId: "G1H2I3J4",
|
||||
listenerId: "L1357924",
|
||||
username: "diana",
|
||||
hostname: "WORKSTATION-04",
|
||||
domain: "HR",
|
||||
ip: "192.168.2.15",
|
||||
os: "Windows 10",
|
||||
process: "chrome.exe",
|
||||
pid: 3210,
|
||||
elevated: false,
|
||||
sleep: 90,
|
||||
tasks: @[],
|
||||
firstCheckin: now() - initDuration(hours = 4),
|
||||
latestCheckin: now() - initDuration(minutes = 2),
|
||||
sessionKey: [byte 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -50,6 +84,7 @@ proc SessionsTable*(title: string): SessionsTableComponent =
|
||||
result = new SessionsTableComponent
|
||||
result.title = title
|
||||
result.agents = exampleAgents
|
||||
result.selection = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
||||
|
||||
proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
|
||||
@@ -62,13 +97,12 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||
ImGuiTableFlags_Reorderable.int32 or
|
||||
ImGuiTableFlags_Hideable.int32 or
|
||||
ImGuiTableFlags_HighlightHoveredColumn.int32 or
|
||||
ImGuiTableFlags_ContextMenuInBody.int32 or
|
||||
ImGuiTableFlags_RowBg.int32 or
|
||||
ImGuiTableFlags_BordersV.int32 or
|
||||
ImGuiTableFlags_BordersH.int32 or
|
||||
ImGuiTableFlags_ScrollY.int32 or
|
||||
ImGuiTableFlags_ScrollX.int32 or
|
||||
ImGuiTableFlags_NoBordersInBodyUntilResize.int32 or
|
||||
ImGuiTableFlags_NoBordersInBodyUntilResize.int32 or
|
||||
ImGui_TableFlags_SizingStretchProp.int32
|
||||
)
|
||||
|
||||
@@ -86,12 +120,20 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||
|
||||
igTableSetupScrollFreeze(0, 1)
|
||||
igTableHeadersRow()
|
||||
|
||||
var multiSelectIO = igBeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape.int32 or ImGuiMultiSelectFlags_BoxSelect1d.int32, component.selection[].Size, int32(component.agents.len()))
|
||||
ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO)
|
||||
|
||||
for row in 0..< component.agents.len():
|
||||
|
||||
igTableNextRow(ImGuiTableRowFlags_None.int32, 0.0f)
|
||||
let agent = component.agents[row]
|
||||
if igTableSetColumnIndex(0):
|
||||
igText(agent.agentId)
|
||||
|
||||
if igTableSetColumnIndex(0):
|
||||
# Enable multi-select functionality
|
||||
igSetNextItemSelectionUserData(row)
|
||||
var isSelected = ImGuiSelectionBasicStorage_Contains(component.selection, cast[ImGuiID](row))
|
||||
discard igSelectable_Bool(agent.agentId, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32, vec2(0.0f, 0.0f))
|
||||
if igTableSetColumnIndex(1):
|
||||
igText(agent.ip)
|
||||
if igTableSetColumnIndex(2):
|
||||
@@ -107,6 +149,23 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||
if igTableSetColumnIndex(7):
|
||||
igText(agent.latestCheckin.format("yyyy-MM-dd HH:mm:ss"))
|
||||
|
||||
# Handle right-click context menu
|
||||
# Right-clicking the table header to hide/show columns or reset the layout is only possible when no sessions are selected
|
||||
if component.selection[].Size > 0 and igBeginPopupContextWindow("TableContextMenu", ImGui_PopupFlags_MouseButtonRight.int32):
|
||||
|
||||
if igMenuItem("Interact", "ENTER", false, true):
|
||||
igCloseCurrentPopup()
|
||||
|
||||
if igMenuItem("Remove", "DELETE", false, true):
|
||||
igCloseCurrentPopup()
|
||||
|
||||
igEndPopup()
|
||||
|
||||
|
||||
multiSelectIO = igEndMultiSelect()
|
||||
ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO)
|
||||
|
||||
igEndTable()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user