feat: Add Print Service Tray application with configuration and queue management
- Implemented PrintQueueService with job counting and snapshot retrieval. - Created Form1 as the main entry point for the tray application. - Developed ConfigurationForm for managing printer configurations and document types. - Added models for printer configuration, queue status requests, and responses. - Established ConfigurationService for loading and saving printer configurations. - Introduced ServiceClient for IPC communication with the print service. - Built TrayApplicationContext for managing the system tray icon and status updates. - Added TODO.md for tracking remaining work and future enhancements.
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
using System.Diagnostics;
|
||||
using PrintServiceTray.Services;
|
||||
using PrintServiceTray.Models;
|
||||
|
||||
namespace PrintServiceTray;
|
||||
|
||||
public class TrayApplicationContext : ApplicationContext
|
||||
{
|
||||
private readonly NotifyIcon _trayIcon;
|
||||
private readonly ServiceClient _serviceClient;
|
||||
private readonly System.Windows.Forms.Timer _refreshTimer;
|
||||
private readonly ToolStripMenuItem _queueStatusItem;
|
||||
private readonly ToolStripMenuItem _serviceStatusItem;
|
||||
|
||||
public TrayApplicationContext()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serviceClient = new ServiceClient();
|
||||
|
||||
// Create context menu
|
||||
var contextMenu = new ContextMenuStrip();
|
||||
|
||||
// Service status (at top)
|
||||
_serviceStatusItem = new ToolStripMenuItem("● Service Running")
|
||||
{
|
||||
Enabled = false,
|
||||
Font = new Font(contextMenu.Font, FontStyle.Bold)
|
||||
};
|
||||
contextMenu.Items.Add(_serviceStatusItem);
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
// Queue status section
|
||||
_queueStatusItem = new ToolStripMenuItem("Queue Status")
|
||||
{
|
||||
Enabled = false
|
||||
};
|
||||
contextMenu.Items.Add(_queueStatusItem);
|
||||
|
||||
var viewQueueItem = new ToolStripMenuItem("View Full Queue...");
|
||||
viewQueueItem.Click += ViewQueue_Click;
|
||||
contextMenu.Items.Add(viewQueueItem);
|
||||
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
// Configuration
|
||||
var configureItem = new ToolStripMenuItem("Configure Printers...");
|
||||
configureItem.Click += Configure_Click;
|
||||
contextMenu.Items.Add(configureItem);
|
||||
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
// Exit
|
||||
var exitItem = new ToolStripMenuItem("Exit");
|
||||
exitItem.Click += Exit_Click;
|
||||
contextMenu.Items.Add(exitItem);
|
||||
|
||||
// Create tray icon
|
||||
_trayIcon = new NotifyIcon
|
||||
{
|
||||
Icon = SystemIcons.Information,
|
||||
ContextMenuStrip = contextMenu,
|
||||
Visible = true,
|
||||
Text = "LAAPC Print Service"
|
||||
};
|
||||
|
||||
_trayIcon.DoubleClick += TrayIcon_DoubleClick;
|
||||
|
||||
// Show startup notification
|
||||
_trayIcon.ShowBalloonTip(2000, "LAAPC Print Service", "Tray app started", ToolTipIcon.Info);
|
||||
|
||||
// Set up refresh timer (every 2 seconds)
|
||||
_refreshTimer = new System.Windows.Forms.Timer
|
||||
{
|
||||
Interval = 2000
|
||||
};
|
||||
_refreshTimer.Tick += RefreshTimer_Tick;
|
||||
_refreshTimer.Start();
|
||||
|
||||
// Initial refresh
|
||||
_ = RefreshStatusAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Failed to initialize tray app: {ex.Message}\n\n{ex.StackTrace}",
|
||||
"Initialization Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async void RefreshTimer_Tick(object? sender, EventArgs e)
|
||||
{
|
||||
await RefreshStatusAsync();
|
||||
}
|
||||
|
||||
private async Task RefreshStatusAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = await _serviceClient.GetQueueStatusAsync();
|
||||
|
||||
if (status.Success)
|
||||
{
|
||||
_serviceStatusItem.Text = "● Service Running";
|
||||
_serviceStatusItem.ForeColor = Color.Green;
|
||||
|
||||
// Update queue status
|
||||
if (status.Jobs.Count == 0)
|
||||
{
|
||||
_queueStatusItem.Text = "Queue Status: Empty";
|
||||
_queueStatusItem.DropDownItems.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_queueStatusItem.Text = $"Queue Status ({status.Jobs.Count} {(status.Jobs.Count == 1 ? "job" : "jobs")})";
|
||||
_queueStatusItem.Enabled = true;
|
||||
|
||||
// Update dropdown items with job list
|
||||
_queueStatusItem.DropDownItems.Clear();
|
||||
|
||||
foreach (var job in status.Jobs.Take(10)) // Show max 10 in menu
|
||||
{
|
||||
var statusIcon = job.Status == "Processing" ? "●" : "○";
|
||||
var jobText = $"{statusIcon} {job.Status}: {job.FileName}";
|
||||
|
||||
if (job.PrinterName != null)
|
||||
{
|
||||
jobText += $" ({job.PrinterName})";
|
||||
}
|
||||
|
||||
if (job.CurrentPage.HasValue && job.TotalPages.HasValue)
|
||||
{
|
||||
jobText += $" - Page {job.CurrentPage}/{job.TotalPages}";
|
||||
}
|
||||
|
||||
var jobItem = new ToolStripMenuItem(jobText) { Enabled = false };
|
||||
_queueStatusItem.DropDownItems.Add(jobItem);
|
||||
}
|
||||
|
||||
if (status.Jobs.Count > 10)
|
||||
{
|
||||
_queueStatusItem.DropDownItems.Add(new ToolStripSeparator());
|
||||
var moreItem = new ToolStripMenuItem($"... and {status.Jobs.Count - 10} more")
|
||||
{
|
||||
Enabled = false
|
||||
};
|
||||
_queueStatusItem.DropDownItems.Add(moreItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Update tooltip
|
||||
_trayIcon.Text = status.Jobs.Count == 0
|
||||
? "LAAPC Print Service - Queue empty"
|
||||
: $"LAAPC Print Service - {status.Jobs.Count} job(s) in queue";
|
||||
}
|
||||
else
|
||||
{
|
||||
_serviceStatusItem.Text = "○ Service Not Running";
|
||||
_serviceStatusItem.ForeColor = Color.Red;
|
||||
_queueStatusItem.Text = "Queue Status: Unavailable";
|
||||
_queueStatusItem.DropDownItems.Clear();
|
||||
_trayIcon.Text = "LAAPC Print Service - Not running";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Error refreshing status: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void TrayIcon_DoubleClick(object? sender, EventArgs e)
|
||||
{
|
||||
// Double-click opens full queue view
|
||||
ViewQueue_Click(sender, e);
|
||||
}
|
||||
|
||||
private void ViewQueue_Click(object? sender, EventArgs e)
|
||||
{
|
||||
// TODO: Open queue view window
|
||||
MessageBox.Show("Queue view window coming soon!", "LAAPC Print Service", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
private void Configure_Click(object? sender, EventArgs e)
|
||||
{
|
||||
var configForm = new Forms.ConfigurationForm();
|
||||
configForm.ShowDialog();
|
||||
}
|
||||
|
||||
private void Exit_Click(object? sender, EventArgs e)
|
||||
{
|
||||
_refreshTimer.Stop();
|
||||
_trayIcon.Visible = false;
|
||||
Application.Exit();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_refreshTimer?.Stop();
|
||||
_refreshTimer?.Dispose();
|
||||
_trayIcon?.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user