diff --git a/README.md b/README.md index 8de9ad1..f8b5e28 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Debugalizers Logo

-

πŸ” Debugalizers

+

Debugalizers

Visual Studio 2022 @@ -18,87 +18,172 @@ --- -A **powerful collection** of debug visualizers for Visual Studio, providing beautiful formatting, syntax highlighting, and specialized views for common string data types. Stop squinting at raw JSON in the debugger! 🎯✨ +A **powerful collection** of debug visualizers for Visual Studio, providing beautiful formatting, syntax highlighting, and specialized views for common string data types. Stop squinting at raw JSON in the debugger! --- -## πŸš€ Features +## Updated Interface -- 🎨 **30+ Visualizers** β€” JSON, XML, JWT, Base64, images, and many more -- 🌳 **Multiple Views** β€” Raw, Formatted, Tree, Table, Hex, Rendered, and Image -- πŸ–ŒοΈ **Syntax Highlighting** β€” Beautiful code highlighting via AvalonEdit -- πŸ”Ž **Search** β€” Find text within large content (Ctrl+F) -- πŸ“‹ **Copy & Export** β€” Copy raw/formatted content or export to file -- πŸ–₯️ **Multi-Architecture** β€” Supports both x64 and ARM64 systems +

+ Updated Debugalizers Interface +
+ The new modern Debugalizers interface +

+ +> **Note:** The screenshots below were captured before the UI overhaul. The updated interface shown above features a modernized design with improved theming, rounded corners, and a cleaner layout. All functionality remains the same. --- -## πŸ“¦ Visualizer Catalog +## Screenshots + +

+ Debugalizers List +
+ Choose from 30+ specialized visualizers +

+ + + + + + + + + + + + + + + + + + + + + + +
+ JSON Formatted View +
+ JSON - Formatted View +
+ XML Pretty View +
+ XML - Pretty Printed +
+ HTML Formatted View +
+ HTML - Formatted View +
+ HTML Rendered View +
+ HTML - Rendered Preview +
+ Markdown Rendered View +
+ Markdown - Rendered Preview +
+ JWT Claims View +
+ JWT - Claims Table +
+ Base64 Image View +
+ Base64 - Image Preview +
+ URI Table View +
+ URI - Parsed Components +
+ Connection String Table View +
+ Connection String - Parsed Table +
+ JSON Raw View +
+ JSON - Raw View +
+ +--- -### πŸ“„ Data Formats +## Features + +- **30+ Visualizers** - JSON, XML, JWT, Base64, images, and many more +- **Multiple Views** - Raw, Formatted, Tree, Table, Hex, Rendered, and Image +- **Syntax Highlighting** - Beautiful code highlighting via AvalonEdit +- **Search** - Find text within large content (Ctrl+F) +- **Copy & Export** - Copy raw/formatted content or export to file +- **Multi-Architecture** - Supports both x64 and ARM64 systems + +--- + +## Visualizer Catalog + +### Data Formats | Visualizer | Description | Views | |------------|-------------|-------| -| πŸ“‹ **JSON** | API responses, config files | Formatted, Tree, Raw | -| πŸ“° **XML** | SOAP, config, SVG | Formatted, Tree, Raw | -| 🌐 **HTML** | Web content, email templates | Formatted, Rendered, Tree, Raw | -| βš™οΈ **YAML** | Docker, K8s, CI/CD configs | Formatted, Tree, Raw | -| πŸ”§ **TOML** | Rust configs, pyproject.toml | Formatted, Tree, Raw | -| πŸ“Š **CSV/TSV** | Tabular data exports | Table, Raw | -| πŸ“ **INI** | Legacy config files | Formatted, Table, Raw | -| πŸ“– **Markdown** | Documentation strings | Rendered, Raw | -| πŸ—ƒοΈ **SQL** | Database queries | Formatted, Syntax Highlighted, Raw | -| πŸ”— **GraphQL** | API queries | Formatted, Syntax Highlighted, Raw | - -### πŸ” Encoded Data +| **JSON** | API responses, config files | Formatted, Tree, Raw | +| **XML** | SOAP, config, SVG | Formatted, Tree, Raw | +| **HTML** | Web content, email templates | Formatted, Rendered, Tree, Raw | +| **YAML** | Docker, K8s, CI/CD configs | Formatted, Tree, Raw | +| **TOML** | Rust configs, pyproject.toml | Formatted, Tree, Raw | +| **CSV/TSV** | Tabular data exports | Table, Raw | +| **INI** | Legacy config files | Formatted, Table, Raw | +| **Markdown** | Documentation strings | Rendered, Raw | +| **SQL** | Database queries | Formatted, Syntax Highlighted, Raw | +| **GraphQL** | API queries | Formatted, Syntax Highlighted, Raw | + +### Encoded Data | Visualizer | Description | Views | |------------|-------------|-------| -| πŸ”€ **Base64** | Decode text from Base64 | Decoded, Hex, Raw | -| πŸ–ΌοΈ **Base64 Image** | Embedded images (data:image/...) | Image Preview, Raw | -| πŸ”— **URL Encoded** | Query strings, form data | Decoded, Raw | -| 🏷️ **HTML Entities** | `&` β†’ `&`, `<` β†’ `<` | Decoded, Raw | -| πŸ”‘ **Unicode Escape** | `\u0041` β†’ `A` | Decoded, Raw | -| πŸ”’ **Hex String** | `48656C6C6F` β†’ `Hello` | Decoded, Hex, Raw | -| πŸ“¦ **GZip/Deflate** | Compressed payloads | Decompressed, Raw | +| **Base64** | Decode text from Base64 | Decoded, Hex, Raw | +| **Base64 Image** | Embedded images (data:image/...) | Image Preview, Raw | +| **URL Encoded** | Query strings, form data | Decoded, Raw | +| **HTML Entities** | `&` to `&`, `<` to `<` | Decoded, Raw | +| **Unicode Escape** | `\u0041` to `A` | Decoded, Raw | +| **Hex String** | `48656C6C6F` to `Hello` | Decoded, Hex, Raw | +| **GZip/Deflate** | Compressed payloads | Decompressed, Raw | -### πŸ›‘οΈ Security & Auth Tokens +### Security & Auth Tokens | Visualizer | Description | Views | |------------|-------------|-------| -| 🎫 **JWT** | Decode header, payload, expiry | Claims Table, Decoded, Raw | -| πŸ”‘ **SAML** | Decode assertions | XML Tree, Claims, Raw | -| πŸ“œ **X.509 Certificate** | PEM/DER certificates | Details Table, Raw | +| **JWT** | Decode header, payload, expiry | Claims Table, Decoded, Raw | +| **SAML** | Decode assertions | XML Tree, Claims, Raw | +| **X.509 Certificate** | PEM/DER certificates | Details Table, Raw | -### πŸ”— Structured Strings +### Structured Strings | Visualizer | Description | Views | |------------|-------------|-------| -| πŸ”Œ **Connection String** | DB/service connections | Parsed Table, Raw | -| 🌍 **URI/URL** | Full URL parsing | Parsed Parts, Query Params Table | -| ❓ **Query String** | `?foo=bar&baz=qux` | Key-Value Table, Raw | -| 🎯 **Regex** | Pattern visualization | Pattern Breakdown, Raw | -| ⏰ **Cron Expression** | Schedule expressions | Human Readable, Next Runs | +| **Connection String** | DB/service connections | Parsed Table, Raw | +| **URI/URL** | Full URL parsing | Parsed Parts, Query Params Table | +| **Query String** | `?foo=bar&baz=qux` | Key-Value Table, Raw | +| **Regex** | Pattern visualization | Pattern Breakdown, Raw | +| **Cron Expression** | Schedule expressions | Human Readable, Next Runs | -### πŸ’Ύ Binary & Low-Level +### Binary & Low-Level | Visualizer | Description | Views | |------------|-------------|-------| -| πŸ”’ **Hex Dump** | Binary data as hex | Hex + ASCII | -| πŸ†” **GUID/UUID** | Format and version info | Formatted, Details | -| πŸ• **Timestamp** | Unix epoch conversion | Human Readable, UTC/Local | -| 🌐 **IP Address** | IPv4/IPv6 details | Formatted, CIDR Info | +| **Hex Dump** | Binary data as hex | Hex + ASCII | +| **GUID/UUID** | Format and version info | Formatted, Details | +| **Timestamp** | Unix epoch conversion | Human Readable, UTC/Local | +| **IP Address** | IPv4/IPv6 details | Formatted, CIDR Info | --- -## πŸ“₯ Installation +## Installation ### From Visual Studio Marketplace [![VS Marketplace](https://img.shields.io/badge/VS%20Marketplace-Debugalizers-purple?style=for-the-badge&logo=visualstudio&logoColor=white)](https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.VS-Debugalizers) 1. Open Visual Studio 2022 -2. Go to **Extensions** β†’ **Manage Extensions** +2. Go to **Extensions** > **Manage Extensions** 3. Search for "**Debugalizers**" 4. Click **Download** and restart Visual Studio @@ -119,84 +204,90 @@ dotnet test src/CodingWithCalvin.Debugalizers.slnx --- -## πŸš€ Usage +## Usage + +1. Set a breakpoint where a string variable is in scope +2. When the debugger hits the breakpoint, hover over the variable +3. Click the **magnifying glass** icon in the DataTip +4. Select the appropriate visualizer (e.g., "**Debugalizers: JSON**") +5. The visualizer window opens with beautifully formatted content! -1. πŸ”΄ Set a breakpoint where a string variable is in scope -2. ⏸️ When the debugger hits the breakpoint, hover over the variable -3. πŸ” Click the **magnifying glass** icon in the DataTip -4. πŸ“‹ Select the appropriate visualizer (e.g., "**Debugalizers: JSON**") -5. ✨ The visualizer window opens with beautifully formatted content! +

+ Selecting a Visualizer +
+ Select a visualizer from the list +

-### ⌨️ Keyboard Shortcuts +### Keyboard Shortcuts | Shortcut | Action | |----------|--------| -| `Ctrl+F` | πŸ”Ž Search within content | -| `Escape` | ❌ Close visualizer window | +| `Ctrl+F` | Search within content | +| `Escape` | Close visualizer window | -### πŸ› οΈ Toolbar Actions +### Toolbar Actions | Button | Action | |--------|--------| -| πŸ“‹ **Copy** | Copy raw content to clipboard | -| πŸ“ **Copy Formatted** | Copy formatted content to clipboard | -| πŸ’Ύ **Export** | Save content to a file | -| ↩️ **Word Wrap** | Toggle word wrapping | +| **Copy** | Copy raw content to clipboard | +| **Copy Formatted** | Copy formatted content to clipboard | +| **Export** | Save content to a file | +| **Word Wrap** | Toggle word wrapping | --- -## πŸ“‹ Requirements +## Requirements -- πŸ’» Visual Studio 2022 (17.8) or later -- πŸ”§ .NET Framework 4.8 +- Visual Studio 2022 (17.8) or later +- .NET Framework 4.8 --- -## πŸ› οΈ Technology Stack +## Technology Stack | Component | Technology | |-----------|------------| -| 🎨 Syntax Highlighting | AvalonEdit | -| πŸ“Š JSON Parsing | Newtonsoft.Json | -| πŸ“„ YAML Parsing | YamlDotNet | -| πŸ”§ TOML Parsing | Tomlyn | -| 🎫 JWT Decoding | System.IdentityModel.Tokens.Jwt | -| πŸ“– Markdown Rendering | Markdig | -| ⏰ Cron Parsing | NCrontab | -| πŸ“Š CSV Parsing | CsvHelper | +| Syntax Highlighting | AvalonEdit | +| JSON Parsing | Newtonsoft.Json | +| YAML Parsing | YamlDotNet | +| TOML Parsing | Tomlyn | +| JWT Decoding | System.IdentityModel.Tokens.Jwt | +| Markdown Rendering | Markdig | +| Cron Parsing | NCrontab | +| CSV Parsing | CsvHelper | --- -## 🀝 Contributing +## Contributing -Contributions are welcome! Feel free to submit issues and pull requests. πŸ’ͺ +Contributions are welcome! Feel free to submit issues and pull requests. -1. 🍴 Fork the repository -2. 🌿 Create a feature branch (`git checkout -b feat/amazing-feature`) -3. πŸ’Ύ Commit your changes (`git commit -m 'feat: add amazing feature'`) -4. πŸ“€ Push to the branch (`git push origin feat/amazing-feature`) -5. πŸŽ‰ Open a Pull Request +1. Fork the repository +2. Create a feature branch (`git checkout -b feat/amazing-feature`) +3. Commit your changes (`git commit -m 'feat: add amazing feature'`) +4. Push to the branch (`git push origin feat/amazing-feature`) +5. Open a Pull Request --- -## πŸ“„ License +## License -This project is licensed under the **MIT License** β€” see the [LICENSE](LICENSE) file for details. +This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details. --- -## πŸ‘₯ Contributors +## Contributors -[![CalvinAllen](https://avatars.githubusercontent.com/u/41448698?v=4&s=64)](https://github.com/CalvinAllen) [![lennartb-](https://avatars.githubusercontent.com/u/5563601?v=4&s=64)](https://github.com/lennartb-) +[![CalvinAllen](https://avatars.githubusercontent.com/u/41448698?v=4&s=64)](https://github.com/CalvinAllen) [![lennartb-](https://avatars.githubusercontent.com/u/5563601?v=4&s=64)](https://github.com/lennartb-) ---
-### ⭐ If you find Debugalizers useful, please consider giving it a star! ⭐ +### If you find Debugalizers useful, please consider giving it a star! -*Made with ❀️ for the Visual Studio community from Coding With Calvin* +*Made with care for the Visual Studio community from Coding With Calvin*
diff --git a/resources/base64-image.png b/resources/base64-image.png new file mode 100644 index 0000000..b5c104f Binary files /dev/null and b/resources/base64-image.png differ diff --git a/resources/connectionstring-table.png b/resources/connectionstring-table.png new file mode 100644 index 0000000..848e532 Binary files /dev/null and b/resources/connectionstring-table.png differ diff --git a/resources/debugalizers-list.png b/resources/debugalizers-list.png new file mode 100644 index 0000000..7132b70 Binary files /dev/null and b/resources/debugalizers-list.png differ diff --git a/resources/html-formatted.png b/resources/html-formatted.png new file mode 100644 index 0000000..b7c1a63 Binary files /dev/null and b/resources/html-formatted.png differ diff --git a/resources/html-rendered.png b/resources/html-rendered.png new file mode 100644 index 0000000..6e3f848 Binary files /dev/null and b/resources/html-rendered.png differ diff --git a/resources/json-formatted.png b/resources/json-formatted.png new file mode 100644 index 0000000..2f98431 Binary files /dev/null and b/resources/json-formatted.png differ diff --git a/resources/json-raw.png b/resources/json-raw.png new file mode 100644 index 0000000..c14ebe6 Binary files /dev/null and b/resources/json-raw.png differ diff --git a/resources/jwt-claims.png b/resources/jwt-claims.png new file mode 100644 index 0000000..b866b86 Binary files /dev/null and b/resources/jwt-claims.png differ diff --git a/resources/markdown-rendered.png b/resources/markdown-rendered.png new file mode 100644 index 0000000..8ffb6fc Binary files /dev/null and b/resources/markdown-rendered.png differ diff --git a/resources/updated-interface.png b/resources/updated-interface.png new file mode 100644 index 0000000..44a7170 Binary files /dev/null and b/resources/updated-interface.png differ diff --git a/resources/uri-mailto-table.png b/resources/uri-mailto-table.png new file mode 100644 index 0000000..fe3915d Binary files /dev/null and b/resources/uri-mailto-table.png differ diff --git a/resources/uri-table.png b/resources/uri-table.png new file mode 100644 index 0000000..984f656 Binary files /dev/null and b/resources/uri-table.png differ diff --git a/resources/xml-pretty.png b/resources/xml-pretty.png new file mode 100644 index 0000000..20fe619 Binary files /dev/null and b/resources/xml-pretty.png differ diff --git a/samples/DebugalizersSampleApp/DebugalizersSampleApp.csproj b/samples/DebugalizersSampleApp/DebugalizersSampleApp.csproj new file mode 100644 index 0000000..58e5302 --- /dev/null +++ b/samples/DebugalizersSampleApp/DebugalizersSampleApp.csproj @@ -0,0 +1,10 @@ + + + + Exe + net10.0 + disable + enable + + + diff --git a/samples/DebugalizersSampleApp/Program.cs b/samples/DebugalizersSampleApp/Program.cs new file mode 100644 index 0000000..9853a3e --- /dev/null +++ b/samples/DebugalizersSampleApp/Program.cs @@ -0,0 +1,605 @@ +// Sample application for testing Debugalizers extension +// Set breakpoints on lines with "// BREAKPOINT" comments and inspect the variables + +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Text; + +namespace DebugalizersSampleApp; + +public class Program +{ + public static void Main() + { + Console.WriteLine("Debugalizers Sample Application"); + Console.WriteLine("================================"); + Console.WriteLine(); + Console.WriteLine("Set breakpoints on lines marked with '// BREAKPOINT' comments,"); + Console.WriteLine("then use the magnifying glass icon in the debugger to visualize each variable."); + Console.WriteLine(); + + // Run all sample categories + DataFormatSamples(); + EncodedDataSamples(); + SecuritySamples(); + StructuredStringSamples(); + BinaryAndLowLevelSamples(); + + Console.WriteLine(); + Console.WriteLine("All samples completed!"); + } + + #region Data Format Samples (11 visualizers) + + private static void DataFormatSamples() + { + Console.WriteLine("=== Data Format Samples ==="); + + // JSON - Pretty-prints and shows tree view + var json = """ + { + "name": "John Doe", + "age": 30, + "email": "john.doe@example.com", + "address": { + "street": "123 Main St", + "city": "Springfield", + "state": "IL", + "zip": "62701" + }, + "phoneNumbers": [ + { "type": "home", "number": "555-1234" }, + { "type": "work", "number": "555-5678" } + ], + "isActive": true, + "balance": 1234.56 + } + """; + Debugger.Break(); // BREAKPOINT - Inspect 'json' variable + + // JSON Array + var jsonArray = """ + [ + { "id": 1, "name": "Apple", "color": "red" }, + { "id": 2, "name": "Banana", "color": "yellow" }, + { "id": 3, "name": "Orange", "color": "orange" } + ] + """; + Debugger.Break(); // BREAKPOINT - Inspect 'jsonArray' variable + + // XML - Pretty-prints and shows tree view + var xml = """ + + + + The Great Gatsby + F. Scott Fitzgerald + 1925 + 10.99 + + + A Brief History of Time + Stephen Hawking + 1988 + 15.99 + + + """; + Debugger.Break(); // BREAKPOINT - Inspect 'xml' variable + + // HTML - Renders preview and shows formatted source + var html = """ + + + + + Sample Page + + + +

Welcome to Debugalizers

+

This is a sample HTML document.

+ + Visit Example + + + """; + Debugger.Break(); // BREAKPOINT - Inspect 'html' variable + + // YAML - Common configuration format + var yaml = """ + # Application Configuration + application: + name: MyApp + version: 1.0.0 + environment: production + + database: + host: localhost + port: 5432 + name: myapp_db + credentials: + username: admin + password: secret123 + + features: + - name: authentication + enabled: true + - name: caching + enabled: true + ttl: 3600 + - name: logging + enabled: true + level: info + """; + Debugger.Break(); // BREAKPOINT - Inspect 'yaml' variable + + // TOML - Configuration format (common in Rust/Python) + var toml = """ + # This is a TOML document + + title = "TOML Example" + + [owner] + name = "Tom Preston-Werner" + dob = 1979-05-27T07:32:00-08:00 + + [database] + enabled = true + ports = [ 8000, 8001, 8002 ] + data = [ ["delta", "phi"], [3.14] ] + temp_targets = { cpu = 79.5, case = 72.0 } + + [servers] + + [servers.alpha] + ip = "10.0.0.1" + role = "frontend" + + [servers.beta] + ip = "10.0.0.2" + role = "backend" + """; + Debugger.Break(); // BREAKPOINT - Inspect 'toml' variable + + // CSV - Comma-separated values + var csv = """ + Name,Age,Email,Department,Salary + John Doe,30,john@example.com,Engineering,75000 + Jane Smith,28,jane@example.com,Marketing,65000 + Bob Johnson,35,bob@example.com,Sales,70000 + Alice Brown,32,alice@example.com,HR,60000 + Charlie Wilson,40,charlie@example.com,Engineering,85000 + """; + Debugger.Break(); // BREAKPOINT - Inspect 'csv' variable + + // TSV - Tab-separated values + var tsv = "Product\tPrice\tQuantity\tCategory\n" + + "Laptop\t999.99\t50\tElectronics\n" + + "Mouse\t29.99\t200\tAccessories\n" + + "Keyboard\t79.99\t150\tAccessories\n" + + "Monitor\t299.99\t75\tElectronics"; + Debugger.Break(); // BREAKPOINT - Inspect 'tsv' variable + + // INI - Configuration file format + var ini = """ + [General] + AppName=MyApplication + Version=2.0.1 + Debug=false + + [Database] + Server=localhost + Port=3306 + Database=myapp + User=root + + [Logging] + Level=Warning + Path=C:\Logs\app.log + MaxSize=10MB + """; + Debugger.Break(); // BREAKPOINT - Inspect 'ini' variable + + // Markdown - Renders preview + var markdown = """ + # Debugalizers Documentation + + Welcome to **Debugalizers**, a Visual Studio extension for debugging string content. + + ## Features + + - JSON visualization with tree view + - XML pretty-printing + - Base64 decoding + - JWT token inspection + + ### Code Example + + ```csharp + var json = "{ \"name\": \"test\" }"; + // Set breakpoint and use visualizer + ``` + + ## Installation + + 1. Open Visual Studio + 2. Go to Extensions > Manage Extensions + 3. Search for "Debugalizers" + 4. Click Install + + > **Note:** Restart Visual Studio after installation. + + For more info, visit [our website](https://example.com). + """; + Debugger.Break(); // BREAKPOINT - Inspect 'markdown' variable + + // SQL - Syntax highlighting and formatting + var sql = """ + SELECT + u.id, + u.username, + u.email, + COUNT(o.id) as order_count, + SUM(o.total) as total_spent + FROM users u + LEFT JOIN orders o ON u.id = o.user_id + WHERE u.created_at >= '2024-01-01' + AND u.status = 'active' + GROUP BY u.id, u.username, u.email + HAVING COUNT(o.id) > 5 + ORDER BY total_spent DESC + LIMIT 100; + """; + Debugger.Break(); // BREAKPOINT - Inspect 'sql' variable + + // GraphQL - Query language for APIs + var graphql = """ + query GetUserWithOrders($userId: ID!, $limit: Int = 10) { + user(id: $userId) { + id + name + email + profile { + avatar + bio + } + orders(first: $limit, orderBy: { field: CREATED_AT, direction: DESC }) { + edges { + node { + id + total + status + items { + product { + name + price + } + quantity + } + } + } + pageInfo { + hasNextPage + endCursor + } + } + } + } + """; + Debugger.Break(); // BREAKPOINT - Inspect 'graphql' variable + + Console.WriteLine(" Data format samples ready for inspection"); + } + + #endregion + + #region Encoded Data Samples (8 visualizers) + + private static void EncodedDataSamples() + { + Console.WriteLine("=== Encoded Data Samples ==="); + + // Base64 - Encoded text + var base64Text = Convert.ToBase64String(Encoding.UTF8.GetBytes( + "Hello, World! This is a secret message encoded in Base64.")); + Debugger.Break(); // BREAKPOINT - Inspect 'base64Text' variable + + // Base64 - Encoded JSON + var base64Json = Convert.ToBase64String(Encoding.UTF8.GetBytes( + """{"user":"admin","role":"superuser","permissions":["read","write","delete"]}""")); + Debugger.Break(); // BREAKPOINT - Inspect 'base64Json' variable + + // Base64 Image - Small red dot PNG (data URI) + var base64Image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mP8z8BQz0AEYBxVSF+FABJADq/cY1v6AAAAAElFTkSuQmCC"; + Debugger.Break(); // BREAKPOINT - Inspect 'base64Image' variable + + // Base64 Image - Small green square PNG + var base64ImageGreen = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNk+M9Qz0AEYBxVSF+FAAhKDq19sRgvAAAAAElFTkSuQmCC"; + Debugger.Break(); // BREAKPOINT - Inspect 'base64ImageGreen' variable + + // URL Encoded - Common in query strings + var urlEncoded = "name=John%20Doe&email=john.doe%40example.com&message=Hello%2C%20World%21%20This%20is%20a%20test%20%26%20demo."; + Debugger.Break(); // BREAKPOINT - Inspect 'urlEncoded' variable + + // URL Encoded - Full URL with encoded path + var urlEncodedFull = "https%3A%2F%2Fexample.com%2Fapi%2Fusers%3Fname%3DJohn%20Doe%26filter%3Dactive"; + Debugger.Break(); // BREAKPOINT - Inspect 'urlEncodedFull' variable + + // HTML Entities - Encoded HTML content + var htmlEntities = "<div class="container"><p>Hello & Welcome!</p><span>Price: £50 — Special © 2024</span></div>"; + Debugger.Break(); // BREAKPOINT - Inspect 'htmlEntities' variable + + // Unicode Escape - JavaScript-style escaped string + var unicodeEscape = @"Hello \u0057\u006f\u0072\u006c\u0064! \u4f60\u597d \u0048\u0065\u006c\u006c\u006f"; + Debugger.Break(); // BREAKPOINT - Inspect 'unicodeEscape' variable + + // Hex String - Hexadecimal encoded data + var hexString = "48656c6c6f2c20576f726c6421205468697320697320612068657820656e636f64656420737472696e672e"; + Debugger.Break(); // BREAKPOINT - Inspect 'hexString' variable + + // GZip Compressed - Base64 encoded gzip data + var gzipData = CreateGzipBase64("This is compressed content using GZip compression algorithm."); + Debugger.Break(); // BREAKPOINT - Inspect 'gzipData' variable + + // Deflate Compressed - Base64 encoded deflate data + var deflateData = CreateDeflateBase64("This is compressed content using Deflate compression algorithm."); + Debugger.Break(); // BREAKPOINT - Inspect 'deflateData' variable + + Console.WriteLine(" Encoded data samples ready for inspection"); + } + + private static string CreateGzipBase64(string content) + { + using var outputStream = new MemoryStream(); + using (var gzipStream = new GZipStream(outputStream, CompressionMode.Compress)) + { + var bytes = Encoding.UTF8.GetBytes(content); + gzipStream.Write(bytes, 0, bytes.Length); + } + return Convert.ToBase64String(outputStream.ToArray()); + } + + private static string CreateDeflateBase64(string content) + { + using var outputStream = new MemoryStream(); + using (var deflateStream = new DeflateStream(outputStream, CompressionMode.Compress)) + { + var bytes = Encoding.UTF8.GetBytes(content); + deflateStream.Write(bytes, 0, bytes.Length); + } + return Convert.ToBase64String(outputStream.ToArray()); + } + + #endregion + + #region Security Samples (3 visualizers) + + private static void SecuritySamples() + { + Console.WriteLine("=== Security Samples ==="); + + // JWT - JSON Web Token (this is a sample token, not a real secret) + var jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZW1haWwiOiJqb2huQGV4YW1wbGUuY29tIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDI2MjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; + Debugger.Break(); // BREAKPOINT - Inspect 'jwt' variable + + // JWT with more claims + var jwtComplex = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0xMjMifQ.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzEyMzQ1Iiwi" + + "YXVkIjpbImFwaS5leGFtcGxlLmNvbSIsIm15YXBwLmV4YW1wbGUuY29tIl0sImV4cCI6MTcwNDA2NzIwMCwiaWF0IjoxNzA0MDYzNjAwLCJuYmYiOjE3MDQwNjM2MDAsImp0aSI6" + + "InVuaXF1ZS10b2tlbi1pZC0xMjMiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwicGVybWlzc2lvbnMiOlsicmVhZDp1c2VycyIsIndyaXRlOnVzZXJzIiwiZGVsZXRl" + + "OnVzZXJzIl19.signature_placeholder"; + Debugger.Break(); // BREAKPOINT - Inspect 'jwtComplex' variable + + // SAML Assertion (simplified example) + var saml = """ + + https://idp.example.com + + + john.doe@example.com + + + + + + + + https://sp.example.com + + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:Password + + + + + + john.doe@example.com + + + John + + + Doe + + + admin + user + + + + """; + Debugger.Break(); // BREAKPOINT - Inspect 'saml' variable + + // X.509 Certificate (PEM format - this is a sample/test certificate) + var certificate = """ + -----BEGIN CERTIFICATE----- + MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiUMA0GCSqGSIb3Qw0teleqB0T1G9v3vHlb + EcuF+t2Oie8li0bYO4K9hE6GhQNkwWG8KGYmE0A + YkoCgkfXnBUmlBYVpG0kKDTlz7hqrYVr + WLBXmyMDAwMBAf8wDQYJKoZIhvcNAQELBQADggEBAGIkGhP9aL4MY5CkZ4iJ9yA0 + F7NN91I5vDkvH1d8m4qP9l4Dq0YP5JzCniUl6pGnK9pB6VQNBQE8A4Acb8OVT1k9 + IyB3YNz1V2nV+PJSVY7ELdNOLzlKhU4CDReAxPB6FLSV9wM+xYJzMMDkVvFyLl8t + lNjPrQvCLd8dGLfqBqnPdPeH8DkPx6J9Sx3qVJn7nXJHZqRm0qcE7kKoKtFnVmjy + qkWvC9PKTqNgKjHPuGNc0F54Q0SE4P9VCK0sLr4l4txzqNVRhKGU5E/yCHhAPJCb + pyDiOdDAy/elvFyLZi0bI9yGJnB7 IOuDPBwWeuGm7vJH9vU3pJ0KWv8jH4cA= + -----END CERTIFICATE----- + """; + Debugger.Break(); // BREAKPOINT - Inspect 'certificate' variable + + Console.WriteLine(" Security samples ready for inspection"); + } + + #endregion + + #region Structured String Samples (5 visualizers) + + private static void StructuredStringSamples() + { + Console.WriteLine("=== Structured String Samples ==="); + + // Connection String - SQL Server + var connectionStringSql = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"; + Debugger.Break(); // BREAKPOINT - Inspect 'connectionStringSql' variable + + // Connection String - PostgreSQL + var connectionStringPg = "Host=localhost;Port=5432;Database=mydb;Username=postgres;Password=secret;SSL Mode=Require;Pooling=true;Maximum Pool Size=100;"; + Debugger.Break(); // BREAKPOINT - Inspect 'connectionStringPg' variable + + // Connection String - MongoDB + var connectionStringMongo = "mongodb+srv://username:password@cluster0.mongodb.net/mydb?retryWrites=true&w=majority&maxPoolSize=50"; + Debugger.Break(); // BREAKPOINT - Inspect 'connectionStringMongo' variable + + // URI - HTTP with all components + var uriHttp = "https://user:pass@api.example.com:8443/v2/users/123/profile?fields=name,email&include=avatar&format=json#section-1"; + Debugger.Break(); // BREAKPOINT - Inspect 'uriHttp' variable + + // URI - File path + var uriFile = "file:///C:/Users/John/Documents/report.pdf"; + Debugger.Break(); // BREAKPOINT - Inspect 'uriFile' variable + + // URI - mailto + var uriMailto = "mailto:support@example.com?subject=Help%20Request&body=I%20need%20assistance%20with..."; + Debugger.Break(); // BREAKPOINT - Inspect 'uriMailto' variable + + // Query String - Complex with arrays + var queryString = "search=debugger&category=tools&tags[]=csharp&tags[]=dotnet&page=1&limit=25&sort=relevance&order=desc&filter[status]=active&filter[type]=extension"; + Debugger.Break(); // BREAKPOINT - Inspect 'queryString' variable + + // Regex - Email validation pattern + var regexEmail = @"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"; + Debugger.Break(); // BREAKPOINT - Inspect 'regexEmail' variable + + // Regex - URL pattern + var regexUrl = @"^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$"; + Debugger.Break(); // BREAKPOINT - Inspect 'regexUrl' variable + + // Regex - Phone number pattern + var regexPhone = @"^(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})$"; + Debugger.Break(); // BREAKPOINT - Inspect 'regexPhone' variable + + // Cron Expression - Every weekday at 9 AM + var cronWeekday = "0 9 * * 1-5"; + Debugger.Break(); // BREAKPOINT - Inspect 'cronWeekday' variable + + // Cron Expression - Every 15 minutes + var cronFifteenMin = "*/15 * * * *"; + Debugger.Break(); // BREAKPOINT - Inspect 'cronFifteenMin' variable + + // Cron Expression - First day of every month at midnight + var cronMonthly = "0 0 1 * *"; + Debugger.Break(); // BREAKPOINT - Inspect 'cronMonthly' variable + + // Cron Expression - Complex schedule + var cronComplex = "30 4 1,15 * 1-5"; + Debugger.Break(); // BREAKPOINT - Inspect 'cronComplex' variable + + Console.WriteLine(" Structured string samples ready for inspection"); + } + + #endregion + + #region Binary and Low-Level Samples (4 visualizers) + + private static void BinaryAndLowLevelSamples() + { + Console.WriteLine("=== Binary and Low-Level Samples ==="); + + // GUID - Standard format + var guid1 = "550e8400-e29b-41d4-a716-446655440000"; + Debugger.Break(); // BREAKPOINT - Inspect 'guid1' variable + + // GUID - Various formats (all same GUID) + var guid2 = "6F9619FF-8B86-D011-B42D-00CF4FC964FF"; + Debugger.Break(); // BREAKPOINT - Inspect 'guid2' variable + + // GUID - As Guid object converted to string + var guid3 = Guid.NewGuid().ToString(); + Debugger.Break(); // BREAKPOINT - Inspect 'guid3' variable + + // IP Address - IPv4 + var ipv4 = "192.168.1.100"; + Debugger.Break(); // BREAKPOINT - Inspect 'ipv4' variable + + // IP Address - IPv4 localhost + var ipv4Localhost = "127.0.0.1"; + Debugger.Break(); // BREAKPOINT - Inspect 'ipv4Localhost' variable + + // IP Address - IPv6 + var ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; + Debugger.Break(); // BREAKPOINT - Inspect 'ipv6' variable + + // IP Address - IPv6 compressed + var ipv6Compressed = "2001:db8:85a3::8a2e:370:7334"; + Debugger.Break(); // BREAKPOINT - Inspect 'ipv6Compressed' variable + + // IP Address - IPv6 localhost + var ipv6Localhost = "::1"; + Debugger.Break(); // BREAKPOINT - Inspect 'ipv6Localhost' variable + + // Unix Timestamp - Seconds (10 digits) - January 1, 2024 00:00:00 UTC + var timestampSeconds = "1704067200"; + Debugger.Break(); // BREAKPOINT - Inspect 'timestampSeconds' variable + + // Unix Timestamp - Milliseconds (13 digits) + var timestampMillis = "1704067200000"; + Debugger.Break(); // BREAKPOINT - Inspect 'timestampMillis' variable + + // Unix Timestamp - Current time + var timestampNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); + Debugger.Break(); // BREAKPOINT - Inspect 'timestampNow' variable + + // Hex Dump - Binary data represented for hex view + var hexDumpData = "The quick brown fox jumps over the lazy dog. 0123456789 !@#$%^&*()"; + Debugger.Break(); // BREAKPOINT - Inspect 'hexDumpData' variable + + // Binary data as string for hex dump viewing + var binaryString = Encoding.UTF8.GetString(new byte[] { + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, + 0x72, 0x6C, 0x64, 0x21, 0x00, 0x01, 0x02, 0x03, + 0xFF, 0xFE, 0xFD, 0xFC, 0x0A, 0x0D, 0x09, 0x20 + }); + Debugger.Break(); // BREAKPOINT - Inspect 'binaryString' variable + + Console.WriteLine(" Binary and low-level samples ready for inspection"); + } + + #endregion +} diff --git a/src/CodingWithCalvin.Debugalizers.Core/Services/ContentFormatter.cs b/src/CodingWithCalvin.Debugalizers.Core/Services/ContentFormatter.cs index 55f2ccd..b3bd05f 100644 --- a/src/CodingWithCalvin.Debugalizers.Core/Services/ContentFormatter.cs +++ b/src/CodingWithCalvin.Debugalizers.Core/Services/ContentFormatter.cs @@ -37,6 +37,7 @@ public static string Format(string content, VisualizerType type) VisualizerType.Yaml => FormatYaml(content), VisualizerType.Toml => FormatToml(content), VisualizerType.Sql => FormatSql(content), + VisualizerType.Regex => FormatRegex(content), _ => content }; } @@ -185,6 +186,87 @@ public static string FormatSql(string sql) return result.TrimStart(); } + /// + /// Formats a regular expression with analysis of its components. + /// + /// The regex pattern to format. + /// The formatted regex with explanations. + public static string FormatRegex(string regex) + { + var sb = new StringBuilder(); + sb.AppendLine("Pattern:"); + sb.AppendLine(regex); + sb.AppendLine(); + sb.AppendLine("Analysis:"); + sb.AppendLine(new string('-', 50)); + + // Common regex components and their meanings + var components = new (string pattern, string description)[] + { + (@"^\^", "^ - Start of string/line"), + (@"\$$", "$ - End of string/line"), + (@"\\d", "\\d - Digit [0-9]"), + (@"\\D", "\\D - Non-digit"), + (@"\\w", "\\w - Word character [a-zA-Z0-9_]"), + (@"\\W", "\\W - Non-word character"), + (@"\\s", "\\s - Whitespace"), + (@"\\S", "\\S - Non-whitespace"), + (@"\\b", "\\b - Word boundary"), + (@"\.", ". - Any character (except newline)"), + (@"\+", "+ - One or more"), + (@"\*", "* - Zero or more"), + (@"\?", "? - Zero or one (optional)"), + (@"\{(\d+)\}", "{n} - Exactly n times"), + (@"\{(\d+),\}", "{n,} - At least n times"), + (@"\{(\d+),(\d+)\}", "{n,m} - Between n and m times"), + (@"\[.*?\]", "[...] - Character class"), + (@"\(.*?\)", "(...) - Capturing group"), + (@"\(\?:.*?\)", "(?:...) - Non-capturing group"), + (@"\(\?=.*?\)", "(?=...) - Positive lookahead"), + (@"\(\?!.*?\)", "(?!...) - Negative lookahead"), + (@"\(\?<=.*?\)", "(?<=...) - Positive lookbehind"), + (@"\(\?(); + foreach (var (pattern, description) in components) + { + if (System.Text.RegularExpressions.Regex.IsMatch(regex, pattern)) + { + foundComponents.Add(description); + } + } + + if (foundComponents.Count > 0) + { + foreach (var component in foundComponents) + { + sb.AppendLine(component); + } + } + else + { + sb.AppendLine("(literal pattern - matches exactly)"); + } + + // Try to validate the regex + sb.AppendLine(); + sb.AppendLine("Validation:"); + sb.AppendLine(new string('-', 50)); + try + { + var _ = new System.Text.RegularExpressions.Regex(regex); + sb.AppendLine("βœ“ Valid regex pattern"); + } + catch (System.ArgumentException ex) + { + sb.AppendLine($"βœ— Invalid regex: {ex.Message}"); + } + + return sb.ToString(); + } + /// /// Gets statistics about the content. /// diff --git a/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TableViewControl.xaml.cs b/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TableViewControl.xaml.cs index e311361..4f314c1 100644 --- a/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TableViewControl.xaml.cs +++ b/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TableViewControl.xaml.cs @@ -11,6 +11,7 @@ using CodingWithCalvin.Debugalizers.Visualizers; using CsvHelper; using CsvHelper.Configuration; +using NCrontab; namespace CodingWithCalvin.Debugalizers.UI.Views; @@ -39,6 +40,10 @@ public TableViewControl(string content, VisualizerType type) VisualizerType.QueryString => ParseQueryString(content), VisualizerType.Jwt => ParseJwt(content), VisualizerType.Uri => ParseUri(content), + VisualizerType.Cron => ParseCron(content), + VisualizerType.Guid => ParseGuid(content), + VisualizerType.Timestamp => ParseTimestamp(content), + VisualizerType.IpAddress => ParseIpAddress(content), _ => ParseKeyValue(content) }; @@ -279,4 +284,167 @@ private DataTable ParseKeyValue(string content) return table; } + + private DataTable ParseCron(string content) + { + var table = new DataTable(); + table.Columns.Add("Field"); + table.Columns.Add("Value"); + table.Columns.Add("Description"); + + var parts = content.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + + var fieldNames = new[] { "Minute", "Hour", "Day of Month", "Month", "Day of Week" }; + var fieldRanges = new[] { "0-59", "0-23", "1-31", "1-12", "0-6 (Sun-Sat)" }; + + for (var i = 0; i < Math.Min(parts.Length, fieldNames.Length); i++) + { + table.Rows.Add(fieldNames[i], parts[i], $"Range: {fieldRanges[i]}"); + } + + // Try to parse and show next occurrences + try + { + var schedule = CrontabSchedule.Parse(content); + var now = DateTime.Now; + table.Rows.Add("", "", ""); + table.Rows.Add("Next Occurrences", "", ""); + + for (var i = 0; i < 5; i++) + { + var next = schedule.GetNextOccurrence(now); + table.Rows.Add($" {i + 1}", next.ToString("yyyy-MM-dd HH:mm:ss"), next.ToString("dddd")); + now = next; + } + } + catch + { + table.Rows.Add("Error", "Could not parse cron expression", ""); + } + + return table; + } + + private DataTable ParseGuid(string content) + { + var table = new DataTable(); + table.Columns.Add("Format"); + table.Columns.Add("Value"); + + if (Guid.TryParse(content.Trim(), out var guid)) + { + table.Rows.Add("Standard (D)", guid.ToString("D")); + table.Rows.Add("No Hyphens (N)", guid.ToString("N")); + table.Rows.Add("Braces (B)", guid.ToString("B")); + table.Rows.Add("Parentheses (P)", guid.ToString("P")); + table.Rows.Add("Hex (X)", guid.ToString("X")); + table.Rows.Add("", ""); + table.Rows.Add("Version", ((guid.ToByteArray()[7] & 0xF0) >> 4).ToString()); + table.Rows.Add("Variant", (guid.ToByteArray()[8] & 0xC0) == 0x80 ? "RFC 4122" : "Other"); + } + else + { + table.Rows.Add("Error", "Invalid GUID format"); + } + + return table; + } + + private DataTable ParseTimestamp(string content) + { + var table = new DataTable(); + table.Columns.Add("Format"); + table.Columns.Add("Value"); + + if (long.TryParse(content.Trim(), out var timestamp)) + { + var isMilliseconds = timestamp > 9999999999L; + var dateTime = isMilliseconds + ? DateTimeOffset.FromUnixTimeMilliseconds(timestamp) + : DateTimeOffset.FromUnixTimeSeconds(timestamp); + + table.Rows.Add("Type", isMilliseconds ? "Milliseconds" : "Seconds"); + table.Rows.Add("Unix Timestamp", timestamp.ToString()); + table.Rows.Add("", ""); + table.Rows.Add("UTC", dateTime.UtcDateTime.ToString("yyyy-MM-dd HH:mm:ss.fff")); + table.Rows.Add("Local", dateTime.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss.fff zzz")); + table.Rows.Add("ISO 8601", dateTime.ToString("O")); + table.Rows.Add("", ""); + table.Rows.Add("Day of Week", dateTime.DayOfWeek.ToString()); + table.Rows.Add("Day of Year", dateTime.DayOfYear.ToString()); + table.Rows.Add("Week of Year", GetWeekOfYear(dateTime.DateTime).ToString()); + } + else + { + table.Rows.Add("Error", "Invalid timestamp format"); + } + + return table; + } + + private DataTable ParseIpAddress(string content) + { + var table = new DataTable(); + table.Columns.Add("Property"); + table.Columns.Add("Value"); + + if (System.Net.IPAddress.TryParse(content.Trim(), out var ip)) + { + table.Rows.Add("Address", ip.ToString()); + table.Rows.Add("Address Family", ip.AddressFamily.ToString()); + + if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) + { + // IPv4 + var bytes = ip.GetAddressBytes(); + var reversedBytes = new byte[bytes.Length]; + Array.Copy(bytes, reversedBytes, bytes.Length); + Array.Reverse(reversedBytes); + table.Rows.Add("Binary", string.Join(".", bytes.Select(b => Convert.ToString(b, 2).PadLeft(8, '0')))); + table.Rows.Add("Decimal", BitConverter.ToUInt32(reversedBytes, 0).ToString()); + table.Rows.Add("Hex", string.Join(":", bytes.Select(b => b.ToString("X2")))); + table.Rows.Add("", ""); + table.Rows.Add("Is Private", IsPrivateIP(ip) ? "Yes" : "No"); + table.Rows.Add("Is Loopback", System.Net.IPAddress.IsLoopback(ip) ? "Yes" : "No"); + table.Rows.Add("Class", GetIPClass(bytes[0])); + } + else + { + // IPv6 + table.Rows.Add("Full Form", ip.ToString()); + table.Rows.Add("Is Loopback", System.Net.IPAddress.IsLoopback(ip) ? "Yes" : "No"); + table.Rows.Add("Is Link Local", ip.IsIPv6LinkLocal ? "Yes" : "No"); + table.Rows.Add("Is Site Local", ip.IsIPv6SiteLocal ? "Yes" : "No"); + } + } + else + { + table.Rows.Add("Error", "Invalid IP address format"); + } + + return table; + } + + private static bool IsPrivateIP(System.Net.IPAddress ip) + { + var bytes = ip.GetAddressBytes(); + return bytes[0] == 10 || + (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31) || + (bytes[0] == 192 && bytes[1] == 168); + } + + private static string GetIPClass(byte firstOctet) + { + if (firstOctet < 128) return "A"; + if (firstOctet < 192) return "B"; + if (firstOctet < 224) return "C"; + if (firstOctet < 240) return "D (Multicast)"; + return "E (Reserved)"; + } + + private static int GetWeekOfYear(DateTime date) + { + var cal = CultureInfo.InvariantCulture.Calendar; + return cal.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); + } } diff --git a/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TreeViewControl.xaml b/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TreeViewControl.xaml index b8c38de..d29194b 100644 --- a/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TreeViewControl.xaml +++ b/src/CodingWithCalvin.Debugalizers.Visualizers/UI/Views/TreeViewControl.xaml @@ -1,6 +1,9 @@ + + + - - - diff --git a/src/CodingWithCalvin.Debugalizers.Visualizers/UI/VisualizerWindow.xaml b/src/CodingWithCalvin.Debugalizers.Visualizers/UI/VisualizerWindow.xaml index 7ba6840..15f1dde 100644 --- a/src/CodingWithCalvin.Debugalizers.Visualizers/UI/VisualizerWindow.xaml +++ b/src/CodingWithCalvin.Debugalizers.Visualizers/UI/VisualizerWindow.xaml @@ -3,49 +3,247 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:views="clr-namespace:CodingWithCalvin.Debugalizers.UI.Views" Title="Debugalizers" - Width="900" - Height="600" - MinWidth="600" - MinHeight="400" + Width="1000" + Height="700" + MinWidth="700" + MinHeight="500" WindowStartupLocation="CenterScreen" - Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"> + Background="{DynamicResource BackgroundBrush}"> - - + + + + + + + + + + + + @@ -56,39 +254,178 @@ - - -