LogViewGadget PBI
Posted: Fri Oct 31, 2025 6:11 pm
Always looking for better ways to do things, I worked with my favorite AI guy, and improved my logging ability. Basically a WebGadget used for logging. Hope it works for you, as I only tested it with Win 11 Pro.
Code: Select all
; =============================================================================
; File Name: LogViewGadget.pbi
; Description: WebGadget() based Module that logs your program's information
; Author: Blueb
; Date: Oct 31, 2025
; PB-Version: Tested with 6.30 b4 (x64)
; Typical Usage: SIMPLE colored log gadget with PNG ICONS
; Used in place of the EditorGadget()
;
; Forum:
; =============================================================================
;
; There's a DataSection with some 'generic' icon data. (replace if desired)
DeclareModule LogView
; Color constants
Enumeration
#COLOR_WHITE = 0
#COLOR_GREEN
#COLOR_RED
#COLOR_YELLOW
#COLOR_CYAN
#COLOR_BLUE
EndEnumeration
; Icon constants
Enumeration
#ICON_NONE = 0
#ICON_SUCCESS
#ICON_ERROR
#ICON_WARNING
#ICON_INFO
#ICON_BULLET
EndEnumeration
;Declares
Declare.i LogViewGadget(gadgetID.i, xPos.i, yPos.i, widthVal.i, heightVal.i, bgColor.i = #PB_Default, fontID.i = #PB_Default)
Declare InsertText(gadgetID.i, text$, textColor.i = #COLOR_WHITE, icon.i = #ICON_NONE, textSize.i = #PB_Default, iconSize.i = #PB_Default)
Declare ClearText(gadgetID.i)
Declare SetTextSize(gadgetID.i, textSize.i)
Declare SetIconSize(gadgetID.i, iconSize.i)
Declare SetBackgroundColor(gadgetID.i, bgColor.i)
EndDeclareModule
Module LogView
Structure LogData
htmlContent$
bgColor.i
textSize.i
iconSize.i
EndStructure
Global NewMap Logs.LogData()
; Icon data (loaded from DataSection)
Global IconSuccessData$
Global IconErrorData$
Global IconWarningData$
Global IconInfoData$
Global IconBulletData$
Procedure.s BinaryToDataURI(*start, *end)
; Convert binary PNG data (Data.q) to data URI for HTML
Protected size.i = *end - *start
Protected *buffer = AllocateMemory(size)
Protected result$
If *buffer
CopyMemory(*start, *buffer, size)
result$ = "data:image/png;base64," + Base64Encoder(*buffer, size)
FreeMemory(*buffer)
EndIf
ProcedureReturn result$
EndProcedure
Procedure LoadIconsFromDataSection()
; Convert Data.q binary to base64 data URIs at startup
IconSuccessData$ = BinaryToDataURI(?IconSuccess, ?IconSuccess_End)
IconErrorData$ = BinaryToDataURI(?IconError, ?IconError_End)
IconWarningData$ = BinaryToDataURI(?IconWarning, ?IconWarning_End)
IconInfoData$ = BinaryToDataURI(?IconInfo, ?IconInfo_End)
IconBulletData$ = BinaryToDataURI(?IconBullet, ?IconBullet_End)
EndProcedure
Procedure.s ColorToHex(color.i)
Protected r.i = color & $FF
Protected g.i = (color >> 8) & $FF
Protected b.i = (color >> 16) & $FF
ProcedureReturn "#" + RSet(Hex(r), 2, "0") + RSet(Hex(g), 2, "0") + RSet(Hex(b), 2, "0")
EndProcedure
Procedure.s GetColorClass(textColor.i)
Select textColor
Case #COLOR_GREEN : ProcedureReturn "green"
Case #COLOR_RED : ProcedureReturn "red"
Case #COLOR_YELLOW : ProcedureReturn "yellow"
Case #COLOR_CYAN : ProcedureReturn "cyan"
Case #COLOR_BLUE : ProcedureReturn "blue"
Default : ProcedureReturn "white"
EndSelect
EndProcedure
Procedure.s GetIconHTML(icon.i)
; Generate <img> tag using icon data from DataSection
Select icon
Case #ICON_SUCCESS
ProcedureReturn "<img src='" + IconSuccessData$ + "' class='icon'> "
Case #ICON_ERROR
ProcedureReturn "<img src='" + IconErrorData$ + "' class='icon'> "
Case #ICON_WARNING
ProcedureReturn "<img src='" + IconWarningData$ + "' class='icon'> "
Case #ICON_INFO
ProcedureReturn "<img src='" + IconInfoData$ + "' class='icon'> "
Case #ICON_BULLET
ProcedureReturn "<img src='" + IconBulletData$ + "' class='icon'> "
Default
ProcedureReturn ""
EndSelect
EndProcedure
Procedure.s GetIconDataURI(icon.i)
; Return just the data URI for an icon (for custom sizing)
Select icon
Case #ICON_SUCCESS : ProcedureReturn IconSuccessData$
Case #ICON_ERROR : ProcedureReturn IconErrorData$
Case #ICON_WARNING : ProcedureReturn IconWarningData$
Case #ICON_INFO : ProcedureReturn IconInfoData$
Case #ICON_BULLET : ProcedureReturn IconBulletData$
Default : ProcedureReturn ""
EndSelect
EndProcedure
Procedure.s GetHTMLDocument(gadgetID.i)
Protected LogKey$ = Str(gadgetID)
If Not FindMapElement(Logs(), LogKey$)
ProcedureReturn ""
EndIf
Protected bgColorHex$ = ColorToHex(Logs()\bgColor)
; Determine text color based on background brightness
Protected r.i = Logs()\bgColor & $FF
Protected g.i = (Logs()\bgColor >> 8) & $FF
Protected b.i = (Logs()\bgColor >> 16) & $FF
Protected brightness.i = (r * 299 + g * 587 + b * 114) / 1000
Protected textColor$ = "#333333" ; Dark text for light backgrounds
If brightness < 128
textColor$ = "#d4d4d4" ; Light text for dark backgrounds
EndIf
Protected html$ = "<!DOCTYPE html><html><head><meta charset='utf-8'><style>" +
"body { background:" + bgColorHex$ + "; color:" + textColor$ + "; " +
"font-family:'Consolas','Courier New',monospace; font-size:" + Str(Logs()\textSize) + "pt; " +
"margin:8px; padding:0; overflow-y:auto; }" +
"div { margin:2px 0; padding:0; white-space:pre-wrap; line-height:1.5; }" +
".green { color:#2d9c5e; font-weight:500; }" +
".red { color:#d63030; font-weight:500; }" +
".yellow { color:#c98015; font-weight:500; }" +
".cyan { color:#1976d2; font-weight:500; }" +
".blue { color:#1976d2; font-weight:500; }" +
".white { color:" + textColor$ + "; }" +
".icon { vertical-align:middle; width:" + Str(Logs()\iconSize) + "px; height:" + Str(Logs()\iconSize) + "px; margin-right:4px; }" +
"</style></head><body>" +
Logs()\htmlContent$ +
"<script>window.scrollTo(0, document.body.scrollHeight);</script>" +
"</body></html>"
ProcedureReturn html$
EndProcedure
Procedure UpdateDisplay(gadgetID.i)
SetGadgetItemText(gadgetID, #PB_Web_HtmlCode, GetHTMLDocument(gadgetID))
EndProcedure
Procedure.i LogViewGadget(gadgetID.i, xPos.i, yPos.i, widthVal.i, heightVal.i, bgColor.i = #PB_Default, fontID.i = #PB_Default)
; Load icons from DataSection on first use
Static iconsLoaded.i = #False
If Not iconsLoaded
LoadIconsFromDataSection()
iconsLoaded = #True
EndIf
If bgColor = #PB_Default
bgColor = RGB(255, 255, 255) ; White background by default
EndIf
; Create the WebGadget
Protected result.i = WebGadget(gadgetID, xPos, yPos, widthVal, heightVal, "")
If result
; Store Log data
Protected LogKey$ = Str(gadgetID)
AddMapElement(Logs(), LogKey$)
Logs()\bgColor = bgColor
Logs()\htmlContent$ = ""
Logs()\textSize = 14 ; Default text size (14pt)
Logs()\iconSize = 32 ; Default icon size (32px)
; Give WebGadget a moment to initialize
Delay(50)
; Set initial content
UpdateDisplay(gadgetID)
EndIf
ProcedureReturn result
EndProcedure
Procedure InsertText(gadgetID.i, text$, textColor.i = #COLOR_WHITE, icon.i = #ICON_NONE, textSize.i = #PB_Default, iconSize.i = #PB_Default)
Protected LogKey$ = Str(gadgetID)
If Not FindMapElement(Logs(), LogKey$)
ProcedureReturn
EndIf
; Escape HTML special characters
Protected escaped$ = ReplaceString(text$, "&", "&")
escaped$ = ReplaceString(escaped$, "<", "<")
escaped$ = ReplaceString(escaped$, ">", ">")
; Get color class
Protected colorClass$ = GetColorClass(textColor)
; Build inline style for per-line overrides
Protected inlineStyle$ = ""
If textSize <> #PB_Default
inlineStyle$ + "font-size:" + Str(textSize) + "pt; "
EndIf
; Get icon HTML (with optional size override)
Protected iconHTML$ = ""
If icon <> #ICON_NONE
If iconSize <> #PB_Default
; Custom icon size for this line
iconHTML$ = "<img src='" + GetIconDataURI(icon) + "' style='vertical-align:middle; width:" +
Str(iconSize) + "px; height:" + Str(iconSize) + "px; margin-right:4px;'> "
Else
; Use default icon from class
iconHTML$ = GetIconHTML(icon)
EndIf
EndIf
; Build the div with optional inline styles
If inlineStyle$ <> ""
Logs()\htmlContent$ + "<div class='" + colorClass$ + "' style='" + inlineStyle$ + "'>" + iconHTML$ + escaped$ + "</div>" + #LF$
Else
Logs()\htmlContent$ + "<div class='" + colorClass$ + "'>" + iconHTML$ + escaped$ + "</div>" + #LF$
EndIf
; Update display
UpdateDisplay(gadgetID)
EndProcedure
Procedure ClearText(gadgetID.i)
Protected LogKey$ = Str(gadgetID)
If Not FindMapElement(Logs(), LogKey$)
ProcedureReturn
EndIf
Logs()\htmlContent$ = ""
UpdateDisplay(gadgetID)
EndProcedure
Procedure SetTextSize(gadgetID.i, textSize.i)
Protected LogKey$ = Str(gadgetID)
If Not FindMapElement(Logs(), LogKey$)
ProcedureReturn
EndIf
Logs()\textSize = textSize
UpdateDisplay(gadgetID)
EndProcedure
Procedure SetIconSize(gadgetID.i, iconSize.i)
Protected LogKey$ = Str(gadgetID)
If Not FindMapElement(Logs(), LogKey$)
ProcedureReturn
EndIf
Logs()\iconSize = iconSize
UpdateDisplay(gadgetID)
EndProcedure
Procedure SetBackgroundColor(gadgetID.i, bgColor.i)
Protected LogKey$ = Str(gadgetID)
If Not FindMapElement(Logs(), LogKey$)
ProcedureReturn
EndIf
Logs()\bgColor = bgColor
UpdateDisplay(gadgetID)
EndProcedure
;-----[ Icon Data Section ]-----
; VIBRANT FULL-COLOR PNG ICONS - 32x32 pixels!
; Bright green checkmark, red X, yellow warning, blue info, gray bullet
; To replace: Use PureBasic's "IncludeBinary encoder" on your own PNG files
DataSection
IconSuccess:
; Full-color success icon (32x32 PNG) - 335 bytes
Data.q $0A1A0A0D474E5089,$524448490D000000,$2000000020000000,$7A7A730000000608
Data.q $41444916010000F4,$C211B197E59C7854,$D00B350D05450C30,$8303301309B05252
Data.q $5A4A0A49B0130330,$2C51874A82A6A016,$8A4DF8EE0E52CBF9,$FA26D8B95F4FFA24
Data.q $4FF79F5A5E7ACD77,$1F84D5727775DEED,$5F34801030234CB6,$05DDDB8FB3EA96AC
Data.q $4604532D8D2CDE61,$46D3DF2E654F9903,$04D4214730C80558,$8CA600233A91CC32
Data.q $F0A6421547B65F98,$882398428E699001,$370D200A952106AA,$5B748FC6880701C3
Data.q $EF748046C9BF67D6,$A00DDE89ECBAD006,$898F0021F468DD7D,$F0D2D51640187BA7
Data.q $011FA3453500C39A,$3BAB5673D72972F0,$3404AE7ECFAE7BB4,$DD8AFE9359E89E93
Data.q $5795BBBD1031AD00,$B1964B65227E3244,$4958118D44E6222A,$A329280554D798F4
Data.q $0406409AA98DAD10,$81058173EDFE2BB2,$0D9EF181E464ED28,$142B995EFB17AEBF
Data.q $4900000000AF202E,$00826042AE444E45
IconSuccess_End:
IconError:
; Full-color error icon (32x32 PNG) - 343 bytes
Data.q $0A1A0A0D474E5089,$524448490D000000,$2000000020000000,$7A7A730000000608
Data.q $4144491E010000F4,$020DB197E59C7854,$361A201B0D450C31,$5A6016240A0260A0
Data.q $A0360A0260A24016,$E76C61D055008C41,$C73A777090225F7F,$8F7F9112E5C9C9EF
Data.q $EF787ABD61D06649,$A08E4E135533A7B6,$67CE5F0D01206463,$97C224A776E5EE6E
Data.q $69913C6445047043,$D029A14DE71EB82F,$4701681DB84A8E02,$62D06B4B14087CEA
Data.q $BBA7A95E5680847F,$9E51126BC08026F0,$B33DEA2E814E1125,$0A4DBBAE0480C379
Data.q $24D7F6A205738D66,$048803A8069EB818,$F0338A401282B702,$F40169E161044094
Data.q $045D03EE8022E82B,$EFCA04BC48C705D0,$EA51233811CFFF52,$4ED9A0B4276A5E17
Data.q $4276A02BF44276A4,$BA79A376A21A7891,$672DB6AC91CE22FD,$905BC0A6548B82C2
Data.q $AC72D0C0A615B859,$0485A076EA60ED44,$8124417BEDFE2A72,$0DDEC323119BB344
Data.q $362BB7FA694F1EBF,$4900000000DA74B9,$00826042AE444E45
IconError_End:
IconWarning:
; Full-color warning icon (32x32 PNG) - 301 bytes
Data.q $0A1A0A0D474E5089,$524448490D000000,$2000000020000000,$7A7A730000000608
Data.q $414449F4000000F4,$830E4955ED9C7854,$57D48AB5CB0C0C30,$1F4E78B3C39E08F0
Data.q $0A72EE7A8A5457D1,$325EDA76C7AE210A,$E71838F19ED84017,$2597E7AFB88C1A1A
Data.q $501261116E41AFBF,$CC175AD779016A03,$80255F2987A73C0E,$BDD881C982E356EA
Data.q $1A4E65D880B105C5,$FB8A9404882EA59F,$808AAE36073F3839,$52016028CD72CA08
Data.q $52975C03B178D16B,$B1E48325DA012017,$271C69776822D202,$A3FE345AD4811E02
Data.q $A03903A916AFEB00,$CCD0BD475E4874DD,$E5A7F76C3AFE84BE,$2DF3C8E01D63E076
Data.q $453DF6A00A2FCD28,$C90083859D288A8E,$EBC822BBBF170BC1,$F553928EE7402393
Data.q $9E521C767D6A0276,$39B137EF4F4A0A91,$E240D7C5FFEEABF0,$18D7B046873F8D0D
Data.q $4E454900000000EE,$000000826042AE44
IconWarning_End:
IconInfo:
; Full-color info icon (32x32 PNG) - 310 bytes
Data.q $0A1A0A0D474E5089,$524448490D000000,$2000000020000000,$7A7A730000000608
Data.q $414449FD000000F4,$80E91860639C7854,$E3FF3B0D9A4D1C91,$4499924EE0DEBB92
Data.q $CA218E252967C62B,$54E1284B7396E801,$57811C923DC5F5FB,$18E312967C62D912
Data.q $FAE8E595A2610E5C,$72C3500756214570,$E06C66AC42C11D62,$0EF33A6D9C0ABA74
Data.q $84600C06D3D0735E,$8F8D8E58A495CC00,$B1007563E6C811CD,$22670239B00B9396
Data.q $8E71E801DB2017A4,$EB49BCF003E00D2F,$C1BD7904B00647E0,$CD8804202E6F119D
Data.q $0EA3034DD0C0F805,$CAB89755800E7E18,$80E2882CE4016A6C,$068EB401CB830281
Data.q $811D2D0070C7E0F4,$AF920D02060672CD,$7E2D881BADE1EE2F,$2576401A6B0679F1
Data.q $11338A61A84121A5,$77078AB4C411C352,$EB540188239F00BF,$0386FB5218E29119
Data.q $7B4C9783BE61000E,$45490000000048E0,$0000826042AE444E
IconInfo_End:
IconBullet:
; Full-color bullet icon (32x32 PNG) - 199 bytes
Data.q $0A1A0A0D474E5089,$524448490D000000,$2000000020000000,$7A7A730000000608
Data.q $4144498E000000F4,$800A4196ED9C7854,$CE78110EA7451020,$6A25D0A73AFB47DA
Data.q $FFA344B1FE294825,$8422A344E7FDA996,$EDD79C2EE5D3BF90,$F53EFD51A65B3EB8
Data.q $1F80951113F05082,$4B55ADDF1B73183E,$41131C143C2E02C0,$E7C879FDC3B7FA24
Data.q $DEEED014924A0482,$BAA0500AFDA15681,$F6808326FD97FB80,$A682AFA2202BF682
Data.q $28C449082CE77E13,$8403EE7244A61A76,$541C4186E09CEA90,$49000000001C8D41
Data.q $00826042AE444E45
IconBullet_End:
EndDataSection
;-----[ End of Icon Data Section ]-----
EndModule
;-----[ Test Area ]-----
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
UseModule LogView
Enumeration
#Window_Main
#LogGadget
#Button_Success
#Button_Error
#Button_Warning
#Button_Info
#Button_Clear
#Button_TextBigger
#Button_TextSmaller
#Button_IconBigger
#Button_IconSmaller
#Check_Dark
EndEnumeration
Global currentBgColor.i = RGB(255, 255, 255) ; Start with white
Procedure RecreateLog()
If IsGadget(#LogGadget)
FreeGadget(#LogGadget)
EndIf
LogViewGadget(#LogGadget, 10, 10, 680, 400, currentBgColor, #PB_Default)
; Add demo messages
InsertText(#LogGadget, "=============================================", #COLOR_CYAN)
InsertText(#LogGadget, " LogView WITH FULL-COLOR PNG ICONS!", #COLOR_CYAN)
InsertText(#LogGadget, "=============================================", #COLOR_CYAN)
InsertText(#LogGadget, "", #COLOR_WHITE)
InsertText(#LogGadget, "PNG icons in DataSection (any size supported)", #COLOR_WHITE, #ICON_INFO)
InsertText(#LogGadget, "Change text size globally or per-line", #COLOR_WHITE, #ICON_INFO)
InsertText(#LogGadget, "Change icon size globally or per-line", #COLOR_WHITE, #ICON_INFO)
InsertText(#LogGadget, "Change background color anytime", #COLOR_WHITE, #ICON_INFO)
InsertText(#LogGadget, "", #COLOR_WHITE)
InsertText(#LogGadget, "DEMO OUTPUT:", #COLOR_CYAN)
InsertText(#LogGadget, "---------------------------------------------", #COLOR_WHITE)
InsertText(#LogGadget, "Files copied successfully", #COLOR_GREEN, #ICON_SUCCESS)
InsertText(#LogGadget, "Backup completed", #COLOR_GREEN, #ICON_SUCCESS)
InsertText(#LogGadget, "", #COLOR_WHITE)
; DEMONSTRATE PER-LINE SIZE OVERRIDE - CRITICAL MESSAGE!
InsertText(#LogGadget, "SYSTEM FAILURE DETECTED!", #COLOR_RED, #ICON_ERROR, 20, 48)
InsertText(#LogGadget, "", #COLOR_WHITE)
InsertText(#LogGadget, "WARNING: Low disk space", #COLOR_YELLOW, #ICON_WARNING)
InsertText(#LogGadget, "", #COLOR_WHITE)
InsertText(#LogGadget, "Ready for input!", #COLOR_CYAN, #ICON_INFO)
EndProcedure
If OpenWindow(#Window_Main, 0, 0, 700, 560, "LogViewGadget - Full Control!",
#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
; Create the colored Log
RecreateLog()
; Test buttons - Message types
ButtonGadget(#Button_Success, 10, 420, 130, 30, "Add Success")
ButtonGadget(#Button_Error, 150, 420, 130, 30, "Add Error")
ButtonGadget(#Button_Warning, 290, 420, 130, 30, "Add Warning")
ButtonGadget(#Button_Info, 430, 420, 130, 30, "Add Info")
ButtonGadget(#Button_Clear, 570, 420, 120, 30, "Clear Log")
; Size control buttons
TextGadget(#PB_Any, 10, 462, 100, 20, "Text Size:")
ButtonGadget(#Button_TextSmaller, 110, 460, 80, 25, "Smaller")
ButtonGadget(#Button_TextBigger, 200, 460, 80, 25, "Bigger")
TextGadget(#PB_Any, 310, 462, 100, 20, "Icon Size:")
ButtonGadget(#Button_IconSmaller, 410, 460, 80, 25, "Smaller")
ButtonGadget(#Button_IconBigger, 500, 460, 80, 25, "Bigger")
; Dark mode toggle
CheckBoxGadget(#Check_Dark, 10, 500, 200, 30, "Dark Mode")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case #Button_Success
InsertText(#LogGadget, "Success: Operation completed!", #COLOR_GREEN, #ICON_SUCCESS)
Case #Button_Error
InsertText(#LogGadget, "Error: Something went wrong!", #COLOR_RED, #ICON_ERROR)
Case #Button_Warning
InsertText(#LogGadget, "Warning: Check this issue!", #COLOR_YELLOW, #ICON_WARNING)
Case #Button_Info
InsertText(#LogGadget, "Info: Process is running...", #COLOR_CYAN, #ICON_INFO)
Case #Button_Clear
ClearText(#LogGadget)
InsertText(#LogGadget, "Log cleared! Click buttons to add messages.", #COLOR_CYAN, #ICON_INFO)
Case #Button_TextSmaller
; Decrease text size by 2pt
SetTextSize(#LogGadget, 12)
InsertText(#LogGadget, "Text size decreased to 12pt", #COLOR_CYAN, #ICON_INFO)
Case #Button_TextBigger
; Increase text size by 4pt
SetTextSize(#LogGadget, 18)
InsertText(#LogGadget, "Text size increased to 18pt", #COLOR_CYAN, #ICON_INFO)
Case #Button_IconSmaller
; Decrease icon size
SetIconSize(#LogGadget, 24)
InsertText(#LogGadget, "Icon size decreased to 24px", #COLOR_CYAN, #ICON_INFO)
Case #Button_IconBigger
; Increase icon size
SetIconSize(#LogGadget, 48)
InsertText(#LogGadget, "Icon size increased to 48px", #COLOR_CYAN, #ICON_INFO)
Case #Check_Dark
If GetGadgetState(#Check_Dark)
SetBackgroundColor(#LogGadget, RGB(30, 30, 30)) ; Dark
Else
SetBackgroundColor(#LogGadget, RGB(255, 255, 255)) ; White
EndIf
EndSelect
EndSelect
ForEver
EndIf
CompilerEndIf
;-----[ End of Test Area ]-----

