From a345141a71c0c1bef356316f008aa77831bd8c3a Mon Sep 17 00:00:00 2001 From: Luca Cuzzocrea Date: Sat, 30 Sep 2023 02:39:12 +0200 Subject: [PATCH] Network: better prensentation --- assets/icons/harddisk-symbolic.png | Bin 0 -> 2378 bytes assets/icons/lan-symbolic.png | Bin 0 -> 1398 bytes assets/icons/memory-symbolic.png | Bin 0 -> 1431 bytes assets/icons/network-vpn-symbolic.png | Bin 0 -> 2620 bytes assets/icons/network-wireless-symbolic.png | Bin 0 -> 3942 bytes assets/icons/processor-symbolic.png | Bin 0 -> 1580 bytes code/gui/gui.cpp | 21 ++ code/gui/gui.h | 4 + code/gui/text_draw.cpp | 11 +- code/main.cpp | 330 +++++++++++++++++---- code/render/render.cpp | 3 + code/render/state.h | 3 + 12 files changed, 314 insertions(+), 58 deletions(-) create mode 100644 assets/icons/harddisk-symbolic.png create mode 100644 assets/icons/lan-symbolic.png create mode 100644 assets/icons/memory-symbolic.png create mode 100644 assets/icons/network-vpn-symbolic.png create mode 100644 assets/icons/network-wireless-symbolic.png create mode 100644 assets/icons/processor-symbolic.png diff --git a/assets/icons/harddisk-symbolic.png b/assets/icons/harddisk-symbolic.png new file mode 100644 index 0000000000000000000000000000000000000000..6cbe92a9b8efbc321cbbfb13a0b3d72a24df0b1b GIT binary patch literal 2378 zcmb7`dpOgJAIHDDZ^R6t5kf|!P=uOjt`%vfa+%A}oWxo#%fv>PkwTNUTu*8E=Cr9J z*O*JuQ6gu#oMhcjHDuK}DB?KJ@Ao{vzkh$cKdVSmIWaaVHIf+vq^73Y#3dX% zNsDB}*d#KKmVDZY2LSYl56LZ%RXS4^Qb+Yz+nYJn_sgMM2&;Q|RhI8hH_Vvh?(SNH zP`suo#`o4x4evQU5BFwcCp-~*2A(q#b=~s1H6+q%w{*)0$lSHJ|DV2K2{BVWwEtLLaaeV<)a|mFl3uf zlZGCW>fT2YlutN7reSlM&*g~-2UrJLb`+dz_6`2F&cfsZckP*a<=NdGL<=|cF)lkW znTE%{v26VjVhZ4dK79c!qgPj{$Pmsf^cLSNh9rmfxshUFMlhmpvL&6(6+=^N6fEJ| zD=(LE7-LZnV()X`OX1Kqebz(8jaPUA?`csP`RF1x8f$FQEyZ_5T`^apm4=jw;&BNU zQNiJb?(Hi&?yH2@Kpb-Va$DA0{w785CY>X_RhMU66DAO03tZj{YIIn}#F`#c;}ZRF zSZHDc1?P$k0>PL~x=JzUM(2tpqv3&{+Rim?vK9@|@GNlTP?~PGZaSJMj{E+ma%ce3 z2%D|>0|Og@HOgj4Tkwl$jlxFQe6S)xWA>nIcAhNZ&jKb)hy){ut8I1L2k72XJim@` znO85^W#8e&&ca4M|Lk()TG$PGDZrT@u5&973{`1sOd$AG1>^&`Qp(V5HR&fi^g>%hJ2^DdbRW*&Qr;Wr?!PTK z%e8S^oLx-{>Qe1d^T=!4DSM2}qBoYs3UXZ5H(_=Z4T?`hh*afo(}+Szp%>TV2Xa}v zeKRCw<6pDpy3$8~$NT)=)PWlCS-V7ADp6gsEzBeVC6ypa_6`Q4C0=no<6IHi_`%%C3bL%jOfsxR3B#s4acf^p zxPX;&CphsF%jCa0lJvWrmp#DmuGtsqq-cEPo4S)~vDyOu2rW6%V!1IJ7QFIPEXp5psk0gk;QrLupU8xW)jb)Ji&otipYC3HYXWL!)R!9GfY zn8~l>r!wx>FO{27_2}7vjkx}kRo**(HDC9p8nnriBnk?P3wj@t7wbu0i27L#DsbC% zq}!@KKQi9u74NM1K2*u{QG+np!X*42^O0TgO70JfvSzTws`~bGe^hmZKyt{Rl5W6O zdVS3bM;yliQeBeSJWt!oozQla$44@|ru zjt>A-^_>Rrs z7FkCAlm^3o>yrW$!&zzhOmuENQim1g{SCS!Z3aq&@7p~1VHizdxKguRT{l^D9sHwX z^Bcg{z_{*Jh?n>0@y^d5Uwy@VRXL>LxlotAlYb%yB;wg8ry6;+2Y~%@BIW*VZ;0-0 zHp}pE4d{}q{iRSk$2c}5Kg68}WD-nM;Ns}^-`Skb_r}VBjMcAgILrV!a)y>E1sRZ{ z{wH9t*UPAFHk>aD_rQ$W1j3h9x7!hOBmZJAqM&>Ws5npg+k4_t&)|3d9;@gqWtZat zm(o_?nGzM@!JnKXbQ?h&)S(qf9c+}clg-Hx0-xXsWLdQ$M96gVCUa4@kuE1~qqN2vVFp2SWE$@V0F4?;9NMLOUA zJhr6fA1b|(~o)yIm2i# z>p-p1@dw01rNH|+K**KVwlO!+lBvoK*HM5*;W}xGd>Veq>D^tFKnyllC<9EnU>dMc zC$p-yBWh`-^QIxIjmTrrpE0v(e&3cfn>MACw9p{{ug{<>VVzj<)Ui5x8M4}w!}SQ2 z{m7VeViBab+=XDP-q!4`{5gMYH)R594O^!ET1UpaaAUxhW_oA4DBB*Fr(ruNFB%YY zE-Ye*1)1@o1BJ2fJE+GU-x;m^Ir4eLQ0^Jgr`hekh0EVyGK?W#b%g2))ST~+`i)k7 z(I0!?oMQ%MbspApFofKO7X!MQ$o$xix2i&>VGq%F)ABX{jB)76Q$F~TiHKbqD6g{* QUfn@}kB1-WwtGa@KR0(SW&i*H literal 0 HcmV?d00001 diff --git a/assets/icons/lan-symbolic.png b/assets/icons/lan-symbolic.png new file mode 100644 index 0000000000000000000000000000000000000000..0c16d850821acc1be443a6fbeb7a94527255b278 GIT binary patch literal 1398 zcmcJPYc$k(9L9e$!_Zumnv79q?BrOLC?h4Jkm1N=(Z=R7w#*Q@PX3r#{pBE$wH=+! z$}MZ>RBoklX>wVLkUOdlp&hzqnKF>GPlfxzx3K6w<{N`0*#BB)^DyXKa%o;O|b#G69d{~@PiK+v7kQ#s&FC9slbi_Z7$N^Bp;(;G5i5T6&6T}A2(^j@uFl|i%360Sb4whzQp&KP zt)HRPu(;{jPhrDyCni=--|6%)4jPBggFX#e?hIwQ=O_iv-{C?%bLwuL;J`SI>xYnN z!(1;#o&@R=-djwqkNP4 z=F;w%=3VoTtqYWq)kR9RxtA?G%IjOYNDTQgiQrmg1=k{i`;I5gyvuPHu+eiwB&s|s z_g0~q;kp@$XOlKMp|e{J zy*9(rBRHx1*dy0Abyt}}OO6w*w{q`qeuD-%lP)wRe*Wo?0(LclW?HMl%io}UW_nul zh7Tw^B>-{wfi=n$!&+rJ_8P4lr_c;o7^b)FR?9V2@p9a|XUcF4nyfD;iPr76y&g6a z!o4YFWYQI#4~!s(33LEvhoWZYWd(QzJ`$Si7+i{=+O84m?iGB`+XQE%Na0?q`htLd zRnFp=U6sWAYDvSmUi&L3Q1aDJcWju=D>X+ zzQ6c-Js(a{sJs147wE{texm6e{RYV_GkyFt;MI{5Zp`k(+J*Cu^#tCJNSZT1WK|ec zs|Z9^HC;6=##uZQB~1)wJ3x?yn#<3;fgvT+-U=j|J$pvc?WfF3>W^S7XG#=D)ouNC{E4_6>et_ hW2&(Q13LD|*$mztW(*_m;>yniZihI|RgTfxsl>>mepL!fG0-xzqFm(- zb*N4)RObQ$P~VGWkHOtB}0OQm`ngT>ik8Jn~$=_mO=-12!%~fW3oAnj6{IL;b2** z$(aWjU?MgxBS~o3><9qMR)qy`i_WUlSM50zzt`@`iFZw`myOr#FpAEi%lGmgpQ6RY zlGMqQw&~U+RqexT_4&FV>bzN_;V-YuVT<|_>L7jzWj0pkv9P#ae{!McMyx>?cxgEK z4fl`T8UK7Aa8@ptWKL9STc-`JrP*?gb^7Y#8i*op)mHE;@$Xj@mRp+4@gwPI(Dlv= zrI|(Vqzk_VC5M*sf8w)rYmHYVi`A;;y>0Ftas!MCqrzRD>kDf-Rv8_PEfQL7Z=Qr> zCp9%9K}#@%7Hl$OuT-Q5Z6eGAI8?koAL3miNS4BIlsZ7VAZ-bO6@dMM&93_w9XaB=n_O%y;7Z36@-5hkQw+rbq`VDstUXPs6L#|(pD&ji4{ zC&ag_3zP&rZ>M_UW*+`_%e8`;ntCaYb zbKbKWnI=MfD2P_9$YY~vD6(|YG0-D$(0S%}-{b0puM?f{KAbzebO~ zt+O#FC_BhWW;%Si_o?E(+gn&n#F2oRMVxpK^JwAxkv#XI`SIb5Ni77OG>uCad>Z=8 zFGPMd-W>EAJ(+gy^Wng%Bhw0Il{Ec0O+{2_0&=dW(qq;SW1>8f4U?>k;hphVK)ryT z!nk}he)@nR*Wu5uPQBY6WD`cI#Pc+UT!#bq-S{ZkUB%v_vNDXW}4@n2Rk0p$o#|1Y#&D7+G zsc1^^{(JIg2`k=-dn{vvm8jMMME(VrG(c51+@LR&u6bMHV|y%%IS{02v;9x~sC@6V jz2kFeHcvE*{OpcIr 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 JG@PfU{R86Yo<{%x literal 0 HcmV?d00001 diff --git a/code/gui/gui.cpp b/code/gui/gui.cpp index d0c12c0..743584f 100644 --- a/code/gui/gui.cpp +++ b/code/gui/gui.cpp @@ -506,6 +506,27 @@ bool gui_text_input(Rect r, char *text, u64 max_size) } +// Panels +void gui_panel(Gui_Context *ctx, Rect r) +{ + Gui_Id widget_id = 0; + bool behaviuor = gui_button_behaviuor(ctx, widget_id, r); + + bool is_inactive = true; + v4 background_color = is_inactive ? ctx->style.window_background_color_inactive : +ctx->style.window_background_color; + v4 border_color = is_inactive ? ctx->style.window_border_color_inactive : +ctx->style.window_border_color; + Rect background_rect = {r.x + 0.5, r.y + 0.5, floor(r.w)-1.0, floor(r.h)-1.0}; + r_2d_immediate_rounded_rectangle(background_rect, ctx->style.window_corner_radius, background_color); + r_2d_immediate_rounded_rectangle_outline(background_rect, ctx->style.window_corner_radius, border_color, 1.0); +} + +void gui_panel(Rect r) +{ + gui_panel(&global_gui_state.default_context, r); +} + // Windows bool gui_window_start(Gui_Context *ctx, Rect r, Gui_Id id) diff --git a/code/gui/gui.h b/code/gui/gui.h index d01b2dc..a8ed3aa 100644 --- a/code/gui/gui.h +++ b/code/gui/gui.h @@ -170,6 +170,10 @@ bool gui_image(Rect r, const u8 *bmp, u32 width, u32 height, u32 channels, u32 f bool gui_text_input(Gui_Context *ctx, Rect r, char *text, u64 max_size); bool gui_text_input(Rect r, char *text, u64 max_size); +// Panels +void gui_panel(Gui_Context *ctx, Rect r); +void gui_panel(Rect r); + // Windows bool gui_window_start(Gui_Context *ctx, Rect r, Gui_Id id); // You have to provide some kind of unique id to identify windows bool gui_window_start(Rect r, Gui_Id id); diff --git a/code/gui/text_draw.cpp b/code/gui/text_draw.cpp index 449f59f..6ab1f79 100644 --- a/code/gui/text_draw.cpp +++ b/code/gui/text_draw.cpp @@ -340,12 +340,19 @@ static gui_glyph_texture gui_glyph_texture_create(f32 font_size, u32 capacity) LOG(LOG_DEBUG, "Font size %f not in cache. Slot size (%d %d)", font_size, glyphs.glyph_max_size.x, glyphs.glyph_max_size.y); // Precompile some info data + v2u texture_slots; + texture_slots.x = r_render_state.max_texture_size / glyphs.glyph_max_size.x; + texture_slots.y = (glyphs.capacity + texture_slots.x) / texture_slots.x; for(u32 i = 0; i < glyphs.capacity; i++) { + v2u position = { + i % texture_slots.x * glyphs.glyph_max_size.x, + i / texture_slots.x * glyphs.glyph_max_size.y + }; glyphs.info[i] = gui_glyph_info{ .codepoint = 0xFFFFFFFF, .box = {0,0,0,0}, - .position = v2u{glyphs.glyph_max_size.x * i, 0}, + .position = position, .advance = 0, .next = i + 1, // Last .next will be >= capacity (== capacity to be precise), so we will consider it to be NULL .previous = ((i == 0) ? glyphs.capacity : (i - 1)) @@ -355,7 +362,7 @@ static gui_glyph_texture gui_glyph_texture_create(f32 font_size, u32 capacity) } // Initialize texture - v2s texture_size = v2s{glyphs.glyph_max_size.x * glyphs.capacity, glyphs.glyph_max_size.y}; + v2s texture_size = glyphs.glyph_max_size * V2S(texture_slots); u8 *texture_data = (u8*)p_alloc(sizeof(u8) * texture_size.x * texture_size.y); memset(texture_data, 0, sizeof(u8) * texture_size.x * texture_size.y); diff --git a/code/main.cpp b/code/main.cpp index 5abb97c..524ab46 100644 --- a/code/main.cpp +++ b/code/main.cpp @@ -28,6 +28,14 @@ void process_gui(); void app_init(); void app_deinit(); +enum Section_Status +{ + SECTION_STATUS_NONE, + SECTION_STATUS_OK, + SECTION_STATUS_WARNING, + SECTION_STATUS_ERROR +}; + struct App_Data { f64 glib_iteration_t = -1; @@ -62,6 +70,8 @@ struct System_Info u64 ram_total; u64 ram_used; u64 ram_available; + + Section_Status status; }; struct Network_Device @@ -75,6 +85,8 @@ struct Network_Info { s32 device_count; Network_Device devices[32]; + + Section_Status status; }; struct Virt_Domain @@ -95,6 +107,8 @@ struct Virt_Info { s32 domain_count; Virt_Domain domains[32]; + + Section_Status status; }; struct FS_Entry @@ -110,6 +124,8 @@ struct FS_Info { s32 fs_count; FS_Entry fs[32]; + + Section_Status status; }; System_Info system_info; @@ -118,6 +134,46 @@ Virt_Info virt_info; FS_Info fs_info; App_Data app_data; +Gui_Style style_default; +void style_select(Gui_Context *ctx, Section_Status status) +{ + + switch(status) + { + case SECTION_STATUS_NONE: { + ctx->style.button_color = style_default.button_color; + ctx->style.button_color_hovered = style_default.button_color_hovered; + ctx->style.window_background_color = style_default.window_background_color; + ctx->style.window_background_color_inactive = style_default.window_background_color_inactive; + ctx->style.window_border_color = style_default.window_border_color; + ctx->style.window_border_color_inactive = style_default.window_border_color_inactive; + } break; + case SECTION_STATUS_OK: { + ctx->style.button_color_hovered = ctx->style.button_color = v4{0,1,0,1}; + ctx->style.window_background_color_inactive = ctx->style.window_background_color = v4{0,.6,0,1}; + ctx->style.window_border_color_inactive = ctx->style.window_border_color = v4{0,1,0,1}; + } break; + case SECTION_STATUS_WARNING: { + ctx->style.button_color_hovered = ctx->style.button_color = v4{1,.8,0,1}; + ctx->style.window_background_color_inactive = ctx->style.window_background_color = v4{.6,.5,0,1}; + ctx->style.window_border_color_inactive = ctx->style.window_border_color = v4{1,.8,0,1}; + } break; + case SECTION_STATUS_ERROR: { + ctx->style.button_color_hovered = ctx->style.button_color = v4{1,0,0,1}; + ctx->style.window_background_color_inactive = ctx->style.window_background_color = v4{0.6,0,0,1}; + ctx->style.window_border_color_inactive = ctx->style.window_border_color = v4{1,0,0,1}; + } break; + } +} + +// Icons +r_texture icon_disk; +r_texture icon_lan; +r_texture icon_ram; +r_texture icon_vpn; +r_texture icon_wifi; +r_texture icon_cpu; + u32 seconds_to_duration_text(char *text, f64 seconds, bool show_millis = false) { @@ -147,10 +203,16 @@ u32 seconds_to_duration_text(char *text, f64 seconds, bool show_millis = false) } -void load_image(const char *filename, u8 **data, s32 *width, s32 *height, s32 *channels) +r_texture load_image_monochrome(const char *filename) { + s32 width, height, channels; stbi_set_flip_vertically_on_load(false); - *data = stbi_load(filename, width, height, channels, 4); + u8 *data = stbi_load(filename, &width, &height, &channels, 1); + + for(u64 i = 0; i < (width*height); i++) // Flipped colors + data[i] = 0xFF - data[i]; + + return r_texture_create(data, {width, height}, R_TEXTURE_ALPHA); } @@ -284,94 +346,188 @@ bool process_input() void system_info_gui(Gui_Layout_Grid *grid) { - Rect r = grid->rect_at({0,0}, {4,4}); - Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(v2{0,0}, r.size, 4, 4, 0.2*engine.gui_scaling); + Gui_Context *ctx = &global_gui_state.default_context; + + // No window info + // Clock and date + system_info.time = time(NULL); + struct tm *time_info = localtime(&system_info.time); + char clock[64], timezone[64]; + strftime(clock, 128, "%H:%M:%S", time_info); + strftime(timezone, 128, "%Z", time_info); + + f32 old_font_size = ctx->style.font_size; + ctx->style.font_size *= 3; + gui_text_aligned(grid->rect_at({2,1}, {2,2}), clock, GUI_ALIGN_CENTER); + ctx->style.font_size = old_font_size; + gui_text_aligned(grid->rect_at({2,3}, {2,1}), timezone, GUI_ALIGN_CENTER); + gui_text_aligned(grid->rect_at({2,0}, {2,1}), system_info.cached_date_string, GUI_ALIGN_CENTER); + + // Host + gui_text_aligned(grid->rect_at({0,0}, {2,1}), system_info.hostname, GUI_ALIGN_LEFT); + // Uptime + char uptime[128] = "Uptime: "; seconds_to_duration_text(uptime + strlen("Uptime: "), system_info.uptime); + gui_text_aligned(grid->rect_at({4,0}, {2,1}), uptime, GUI_ALIGN_RIGHT); + + + + // Window with cpu n., load, ram + Rect r = grid->rect_at({4,1}, {2,3}); + Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(v2{0,0}, r.size, 2, 3, 0.2*engine.gui_scaling); + + style_select(ctx, system_info.status); gui_window_start(r, 0xabcdef01); + style_select(ctx, SECTION_STATUS_NONE); - // Host date and time - gui_text_aligned(layout.cell(1), system_info.hostname, GUI_ALIGN_LEFT); - gui_text_aligned(layout.cell(2), system_info.cached_time_string, GUI_ALIGN_CENTER); - gui_text_aligned(layout.cell(1), system_info.cached_date_string, GUI_ALIGN_RIGHT); - - // Load, Memory, Uptime - struct sysinfo sys_info; - sysinfo(&sys_info); - char uptime[128] = "Uptime: "; seconds_to_duration_text(uptime + strlen("Uptime: "), sys_info.uptime); char load[128]; snprintf(load, 128, "Load: %.2f %.2f %.2f", system_info.load[0], system_info.load[1], system_info.load[2]); char processors[128]; snprintf(processors, 128, "CPUs: %d/%d", system_info.cpus_active, system_info.cpus_total); + // slider for ram? char ram[128]; snprintf(ram, 128, "RAM: %.2f/%.2f GiB", system_info.ram_used / (1024.0*1024.0*1024.0), system_info.ram_total / (1024.0*1024.0*1024.0)); - layout.row(2); - gui_text_aligned(layout.cell(1), processors, GUI_ALIGN_LEFT); - gui_text_aligned(layout.cell(1), ram, GUI_ALIGN_LEFT); - gui_text_aligned(layout.cell(2), uptime, GUI_ALIGN_RIGHT); - gui_text_aligned(layout.cell(1), load, GUI_ALIGN_LEFT); - + gui_text_aligned(layout.cell(2), processors, GUI_ALIGN_LEFT); + gui_text_aligned(layout.cell(2), ram, GUI_ALIGN_LEFT); + gui_text_aligned(layout.cell(2), load, GUI_ALIGN_LEFT); gui_window_end(); } void network_gui(Gui_Layout_Grid *grid) { - Rect r = grid->rect_at({0,4}, {4,13}); - Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(v2{0,0}, r.size, 4, 13, 0.2*engine.gui_scaling); - gui_window_start(r, 0xabcdef02); - Gui_Context *ctx = &global_gui_state.default_context; + Rect r = grid->rect_at({0,4}, {3,13}); + Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(v2{0,0}, r.size, 3, 13, 0.2*engine.gui_scaling); + + style_select(ctx, network_info.status); + gui_window_start(r, 0xabcdef02); + style_select(ctx, SECTION_STATUS_NONE); + + gui_text_aligned(layout.cell(GUI_LAYOUT_MAX_CELLS), "Network", GUI_ALIGN_CENTER); + layout.row(); + + r = layout.rect_at({0,1}, layout.max_cells_count - v2s{0,1}); + layout = gui_layout_grid_create_by_divisions(r.position, r.size, 3, 3, 0.2*engine.gui_scaling); + for(s32 i = 0; i < network_info.device_count; i++) { Network_Device *device = &network_info.devices[i]; - gui_button(layout.cell(), device->name); + if(device->type != NM_DEVICE_TYPE_ETHERNET && device->type != NM_DEVICE_TYPE_WIFI && device->type != NM_DEVICE_TYPE_WIREGUARD) + continue; gui_id_stack_push(ctx, gui_id_from_pointer(ctx, device->name)); - switch(device->type) { - case NM_DEVICE_TYPE_ETHERNET: gui_button(layout.cell(), "ETHERNET"); break; - case NM_DEVICE_TYPE_WIFI: gui_button(layout.cell(), "WIFI"); break; - case NM_DEVICE_TYPE_TUN: gui_button(layout.cell(), "TAP or TUN"); break; - case NM_DEVICE_TYPE_BRIDGE: gui_button(layout.cell(), "BRIDGE"); break; - case NM_DEVICE_TYPE_VLAN: gui_button(layout.cell(), "VLAN"); break; - case NM_DEVICE_TYPE_WIREGUARD: gui_button(layout.cell(), "WIREGUARD"); break; - default: gui_button(layout.cell(), ""); break; - } + Section_Status status = SECTION_STATUS_OK; + if(device->state == NM_DEVICE_STATE_PREPARE || + device->state == NM_DEVICE_STATE_CONFIG || + device->state == NM_DEVICE_STATE_IP_CONFIG || + device->state == NM_DEVICE_STATE_IP_CHECK) + { + // Bump status + if(status < SECTION_STATUS_WARNING) + status = SECTION_STATUS_WARNING; + } + else if(device->state != NM_DEVICE_STATE_ACTIVATED) + { + // Bump status + if(status < SECTION_STATUS_ERROR) + status = SECTION_STATUS_ERROR; + } - switch(device->state) - { - case NM_DEVICE_STATE_UNKNOWN: gui_button(layout.cell(), "UNKNOWN"); break; - case NM_DEVICE_STATE_UNMANAGED: gui_button(layout.cell(), "UNMANAGED"); break; - case NM_DEVICE_STATE_UNAVAILABLE: gui_button(layout.cell(), "UNAVAILABLE"); break; - case NM_DEVICE_STATE_DISCONNECTED: gui_button(layout.cell(), "DISCONNECTED"); break; - case NM_DEVICE_STATE_PREPARE: gui_button(layout.cell(), "PREPARE"); break; - case NM_DEVICE_STATE_CONFIG: gui_button(layout.cell(), "CONFIG"); break; - case NM_DEVICE_STATE_NEED_AUTH: gui_button(layout.cell(), "NEED_AUTH"); break; - case NM_DEVICE_STATE_IP_CONFIG: gui_button(layout.cell(), "IP_CONFIG"); break; - case NM_DEVICE_STATE_IP_CHECK: gui_button(layout.cell(), "IP_CHECK"); break; - case NM_DEVICE_STATE_SECONDARIES: gui_button(layout.cell(), "SECONDARIES"); break; - case NM_DEVICE_STATE_ACTIVATED: gui_button(layout.cell(), "ACTIVATED"); break; - case NM_DEVICE_STATE_DEACTIVATING: gui_button(layout.cell(), "DEACTIVATING"); break; - case NM_DEVICE_STATE_FAILED: gui_button(layout.cell(), "FAILED"); break; - default: gui_button(layout.cell(), ""); break; + Rect r = layout.cell(); + style_select(ctx, status); + gui_panel(r); + style_select(ctx, SECTION_STATUS_NONE); + + Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(r.position, r.size, 9, 4, 0.1*engine.gui_scaling); + + const char *type_text = ""; + r_texture *icon = &icon_lan; + switch(device->type) + { + case NM_DEVICE_TYPE_ETHERNET: { + icon = &icon_lan; + type_text = "Ethernet"; + } break; + case NM_DEVICE_TYPE_WIFI: { + icon = &icon_wifi; + type_text = "WiFi"; + } break; + case NM_DEVICE_TYPE_TUN: { + icon = &icon_vpn; + type_text = "TAP/TUN"; + } break; + case NM_DEVICE_TYPE_BRIDGE: { + icon = &icon_lan; + type_text = "Bridge"; + } break; + case NM_DEVICE_TYPE_VLAN: { + icon = &icon_lan; + type_text = "vlan"; + } break; + case NM_DEVICE_TYPE_WIREGUARD: { + icon = &icon_vpn; + type_text = "VPN"; + } break; + default: { + icon = &icon_lan; + type_text = ""; + } break; + } + + const char *state_text = ""; + switch(device->state) + { + case NM_DEVICE_STATE_UNKNOWN: state_text = "UNKNOWN"; break; + case NM_DEVICE_STATE_UNMANAGED: state_text = "UNMANAGED"; break; + case NM_DEVICE_STATE_UNAVAILABLE: state_text = "UNAVAILABLE"; break; + case NM_DEVICE_STATE_DISCONNECTED: state_text = "DISCONNECTED"; break; + case NM_DEVICE_STATE_PREPARE: state_text = "PREPARE"; break; + case NM_DEVICE_STATE_CONFIG: state_text = "CONFIG"; break; + case NM_DEVICE_STATE_NEED_AUTH: state_text = "NEED_AUTH"; break; + case NM_DEVICE_STATE_IP_CONFIG: state_text = "IP_CONFIG"; break; + case NM_DEVICE_STATE_IP_CHECK: state_text = "IP_CHECK"; break; + case NM_DEVICE_STATE_SECONDARIES: state_text = "SECONDARIES"; break; + case NM_DEVICE_STATE_ACTIVATED: state_text = "ACTIVATED"; break; + case NM_DEVICE_STATE_DEACTIVATING: state_text = "DEACTIVATING"; break; + case NM_DEVICE_STATE_FAILED: state_text = "FAILED"; break; + default: gui_button(layout.cell(), ""); break; + } + + Rect icon_r = layout.cell(1); + icon_r.position += (icon_r.size - v2{1,1}*minimum(icon_r.size.x, icon_r.size.y)) * .5; + icon_r.size = v2{1,1} * minimum(icon_r.size.x, icon_r.size.y); + gui_image(icon_r, icon); + gui_text(layout.cell(layout.max_cells_count.x - layout.cursor.x), device->name); + + layout.cell(1); + gui_text(layout.cell(layout.max_cells_count.x - layout.cursor.x), type_text); + + layout.row(2); + layout.cell(1); + gui_text(layout.cell(layout.max_cells_count.x - layout.cursor.x), state_text); } gui_id_stack_pop(ctx); - layout.row(); } gui_window_end(); } void vm_gui(Gui_Layout_Grid *grid) { + Gui_Context *ctx = &global_gui_state.default_context; + Rect r = grid->rect_at({0,17}, {4,5}); Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(v2{0,0}, r.size, 4, 5, 0.2*engine.gui_scaling); - gui_window_start(r, 0xabcdef03); - Gui_Context *ctx = &global_gui_state.default_context; + style_select(ctx, virt_info.status); + gui_window_start(r, 0xabcdef03); + style_select(ctx, SECTION_STATUS_NONE); + Gui_Style old_style = ctx->style; @@ -431,12 +587,16 @@ void vm_gui(Gui_Layout_Grid *grid) void fs_gui(Gui_Layout_Grid *grid) { - Rect r = grid->rect_at({4,0}, {2,22}); - Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(v2{0,0}, r.size, 2, 22, 0.2*engine.gui_scaling); - gui_window_start(r, 0xabcdef04); - Gui_Context *ctx = &global_gui_state.default_context; + Rect r = grid->rect_at({4,4}, {2,18}); + Gui_Layout_Grid layout = gui_layout_grid_create_by_divisions(v2{0,0}, r.size, 2, 18, 0.2*engine.gui_scaling); + + style_select(ctx, fs_info.status); + gui_window_start(r, 0xabcdef04); + style_select(ctx, SECTION_STATUS_NONE); + + for(s32 i = 0; i < fs_info.fs_count; i++) { @@ -509,6 +669,9 @@ void collect_new_data_if_needed() system_info.ram_used = sys_info.totalram * sys_info.mem_unit - system_info.ram_available; + // Status + system_info.status = SECTION_STATUS_NONE; + app_data.system_sample_t = engine.time; } @@ -526,6 +689,30 @@ void collect_new_data_if_needed() network_info.devices[i].state = nm_device_get_state(device); } + // Update section status + network_info.status = SECTION_STATUS_OK; + for(int i = 0; i < network_info.device_count; i++) + { + Network_Device *device = &network_info.devices[i]; + if(device->type == NM_DEVICE_TYPE_ETHERNET || device->type == NM_DEVICE_TYPE_WIREGUARD) + { + if(device->state == NM_DEVICE_STATE_PREPARE || + device->state == NM_DEVICE_STATE_CONFIG || + device->state == NM_DEVICE_STATE_IP_CONFIG || + device->state == NM_DEVICE_STATE_IP_CHECK) + { + // Bump status + if(network_info.status < SECTION_STATUS_WARNING) + network_info.status = SECTION_STATUS_WARNING; + } + else if(device->state != NM_DEVICE_STATE_ACTIVATED) + { + // Bump status + if(network_info.status < SECTION_STATUS_ERROR) + network_info.status = SECTION_STATUS_ERROR; + } + } + } app_data.network_sample_t = engine.time; } @@ -560,6 +747,25 @@ void collect_new_data_if_needed() p_free(domains); + // Update section status + virt_info.status = SECTION_STATUS_OK; + for(int i = 0; i < virt_info.domain_count; i++) + { + Virt_Domain *domain = &virt_info.domains[i]; + if(domain->state == VIR_DOMAIN_PAUSED || + domain->state == VIR_DOMAIN_PMSUSPENDED) + { + // Bump status + if(virt_info.status < SECTION_STATUS_WARNING) + virt_info.status = SECTION_STATUS_WARNING; + } + else if(domain->state != VIR_DOMAIN_RUNNING) + { + // Bump status + if(virt_info.status < SECTION_STATUS_ERROR) + virt_info.status = SECTION_STATUS_ERROR; + } + } app_data.virt_sample_t = engine.time; } @@ -592,6 +798,8 @@ void collect_new_data_if_needed() } endmntent(file); + + fs_info.status = SECTION_STATUS_NONE; } } @@ -635,6 +843,16 @@ void app_init() virt_connection = virConnectOpenReadOnly("qemu:///system"); collect_static_data(); + + style_default = global_gui_state.default_context.style; + + // Icons + icon_disk = load_image_monochrome("assets/icons/harddisk-symbolic.png"); + icon_lan = load_image_monochrome("assets/icons/lan-symbolic.png"); + icon_ram = load_image_monochrome("assets/icons/memory-symbolic.png"); + icon_vpn = load_image_monochrome("assets/icons/network-vpn-symbolic.png"); + icon_wifi = load_image_monochrome("assets/icons/network-wireless-symbolic.png"); + icon_cpu = load_image_monochrome("assets/icons/processor-symbolic.png"); } void app_deinit() diff --git a/code/render/render.cpp b/code/render/render.cpp index ff09771..af865e2 100644 --- a/code/render/render.cpp +++ b/code/render/render.cpp @@ -103,6 +103,9 @@ void r_init() // Render state r_size_update(width, height); + + // Parameters + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &r_render_state.max_texture_size); } void r_deinit() diff --git a/code/render/state.h b/code/render/state.h index feca936..5ac472d 100644 --- a/code/render/state.h +++ b/code/render/state.h @@ -29,6 +29,9 @@ struct r_state // Quads u32 gl_screen_quad_VAO; u32 gl_screen_quad_VBO; + + // Parameters + s32 max_texture_size; }; extern r_state r_render_state;