a08da0217d
- 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.
516 lines
16 KiB
C#
516 lines
16 KiB
C#
using PrintServiceTray.Models;
|
|
using PrintServiceTray.Services;
|
|
|
|
namespace PrintServiceTray.Forms;
|
|
|
|
public partial class ConfigurationForm : Form
|
|
{
|
|
private readonly ConfigurationService _configService;
|
|
private PrinterConfiguration _config;
|
|
private string? _selectedDocType;
|
|
private List<string> _installedPrinters;
|
|
|
|
// UI Controls
|
|
private ListBox _docTypeListBox = null!;
|
|
private Button _newDocTypeButton = null!;
|
|
private Button _deleteDocTypeButton = null!;
|
|
private Panel _pageConfigPanel = null!;
|
|
private RadioButton _saveGlobalRadio = null!;
|
|
private RadioButton _saveLocalRadio = null!;
|
|
private Button _saveButton = null!;
|
|
private Button _cancelButton = null!;
|
|
private Button _addPageButton = null!;
|
|
private Button _removePageButton = null!;
|
|
private Label _configLabel = null!;
|
|
|
|
private List<PageConfigControl> _pageControls = new();
|
|
|
|
public ConfigurationForm()
|
|
{
|
|
_configService = new ConfigurationService();
|
|
_config = _configService.Load();
|
|
_installedPrinters = _configService.GetInstalledPrinters();
|
|
|
|
InitializeComponent();
|
|
LoadDocumentTypes();
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
Text = "LAAPC Printer Configuration";
|
|
Size = new Size(900, 600);
|
|
StartPosition = FormStartPosition.CenterScreen;
|
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
|
MaximizeBox = false;
|
|
|
|
// Left panel - Document Types
|
|
var leftPanel = new Panel
|
|
{
|
|
Location = new Point(10, 10),
|
|
Size = new Size(250, 540),
|
|
BorderStyle = BorderStyle.FixedSingle
|
|
};
|
|
|
|
var docTypeLabel = new Label
|
|
{
|
|
Text = "Document Types:",
|
|
Location = new Point(10, 10),
|
|
Size = new Size(230, 20),
|
|
Font = new Font(Font, FontStyle.Bold)
|
|
};
|
|
|
|
_docTypeListBox = new ListBox
|
|
{
|
|
Location = new Point(10, 35),
|
|
Size = new Size(230, 430)
|
|
};
|
|
_docTypeListBox.SelectedIndexChanged += DocTypeListBox_SelectedIndexChanged;
|
|
|
|
_newDocTypeButton = new Button
|
|
{
|
|
Text = "New",
|
|
Location = new Point(10, 475),
|
|
Size = new Size(110, 30)
|
|
};
|
|
_newDocTypeButton.Click += NewDocType_Click;
|
|
|
|
_deleteDocTypeButton = new Button
|
|
{
|
|
Text = "Delete",
|
|
Location = new Point(130, 475),
|
|
Size = new Size(110, 30)
|
|
};
|
|
_deleteDocTypeButton.Click += DeleteDocType_Click;
|
|
|
|
leftPanel.Controls.AddRange(new Control[] {
|
|
docTypeLabel, _docTypeListBox, _newDocTypeButton, _deleteDocTypeButton
|
|
});
|
|
|
|
// Right panel - Page Configuration
|
|
var rightPanel = new Panel
|
|
{
|
|
Location = new Point(270, 10),
|
|
Size = new Size(610, 540),
|
|
BorderStyle = BorderStyle.FixedSingle
|
|
};
|
|
|
|
_configLabel = new Label
|
|
{
|
|
Text = "Configuration for: (Select a document type)",
|
|
Location = new Point(10, 10),
|
|
Size = new Size(590, 20),
|
|
Font = new Font(Font, FontStyle.Bold)
|
|
};
|
|
|
|
var pageConfigLabel = new Label
|
|
{
|
|
Text = "Page Configuration:",
|
|
Location = new Point(10, 40),
|
|
Size = new Size(590, 20)
|
|
};
|
|
|
|
_pageConfigPanel = new Panel
|
|
{
|
|
Location = new Point(10, 65),
|
|
Size = new Size(590, 350),
|
|
AutoScroll = true,
|
|
BorderStyle = BorderStyle.FixedSingle
|
|
};
|
|
|
|
_addPageButton = new Button
|
|
{
|
|
Text = "+ Add Page",
|
|
Location = new Point(10, 425),
|
|
Size = new Size(120, 30)
|
|
};
|
|
_addPageButton.Click += AddPage_Click;
|
|
|
|
_removePageButton = new Button
|
|
{
|
|
Text = "- Remove Last",
|
|
Location = new Point(140, 425),
|
|
Size = new Size(120, 30)
|
|
};
|
|
_removePageButton.Click += RemovePage_Click;
|
|
|
|
// Save options
|
|
var saveToLabel = new Label
|
|
{
|
|
Text = "Save to:",
|
|
Location = new Point(10, 465),
|
|
Size = new Size(60, 20)
|
|
};
|
|
|
|
_saveGlobalRadio = new RadioButton
|
|
{
|
|
Text = "Global (All Users)",
|
|
Location = new Point(80, 465),
|
|
Size = new Size(150, 20)
|
|
};
|
|
|
|
_saveLocalRadio = new RadioButton
|
|
{
|
|
Text = "Local (My Computer)",
|
|
Location = new Point(240, 465),
|
|
Size = new Size(170, 20),
|
|
Checked = true
|
|
};
|
|
|
|
_saveButton = new Button
|
|
{
|
|
Text = "Save",
|
|
Location = new Point(430, 495),
|
|
Size = new Size(80, 35)
|
|
};
|
|
_saveButton.Click += Save_Click;
|
|
|
|
_cancelButton = new Button
|
|
{
|
|
Text = "Cancel",
|
|
Location = new Point(520, 495),
|
|
Size = new Size(80, 35)
|
|
};
|
|
_cancelButton.Click += (s, e) => Close();
|
|
|
|
rightPanel.Controls.AddRange(new Control[] {
|
|
_configLabel, pageConfigLabel, _pageConfigPanel,
|
|
_addPageButton, _removePageButton,
|
|
saveToLabel, _saveGlobalRadio, _saveLocalRadio,
|
|
_saveButton, _cancelButton
|
|
});
|
|
|
|
Controls.AddRange(new Control[] { leftPanel, rightPanel });
|
|
}
|
|
|
|
private void LoadDocumentTypes()
|
|
{
|
|
_docTypeListBox.Items.Clear();
|
|
foreach (var docType in _config.DocumentTypes.Keys.OrderBy(k => k))
|
|
{
|
|
_docTypeListBox.Items.Add(docType);
|
|
}
|
|
}
|
|
|
|
private void DocTypeListBox_SelectedIndexChanged(object? sender, EventArgs e)
|
|
{
|
|
if (_docTypeListBox.SelectedItem is string docType)
|
|
{
|
|
_selectedDocType = docType;
|
|
LoadPageConfiguration(docType);
|
|
}
|
|
}
|
|
|
|
private void LoadPageConfiguration(string docType)
|
|
{
|
|
_configLabel.Text = $"Configuration for: {docType}";
|
|
_pageConfigPanel.Controls.Clear();
|
|
_pageControls.Clear();
|
|
|
|
if (!_config.DocumentTypes.TryGetValue(docType, out var config))
|
|
{
|
|
config = new DocumentTypeConfig { Name = docType };
|
|
_config.DocumentTypes[docType] = config;
|
|
}
|
|
|
|
int yPos = 10;
|
|
foreach (var page in config.Pages.OrderBy(p => p.PageNumber))
|
|
{
|
|
var pageControl = new PageConfigControl(page.PageNumber, _installedPrinters, _configService);
|
|
pageControl.Location = new Point(10, yPos);
|
|
pageControl.LoadPage(page);
|
|
_pageConfigPanel.Controls.Add(pageControl);
|
|
_pageControls.Add(pageControl);
|
|
yPos += pageControl.Height + 10;
|
|
}
|
|
|
|
if (config.Pages.Count == 0)
|
|
{
|
|
// Add first page by default
|
|
AddPage_Click(null, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
private void AddPage_Click(object? sender, EventArgs e)
|
|
{
|
|
if (_selectedDocType == null) return;
|
|
|
|
var config = _config.DocumentTypes[_selectedDocType];
|
|
int nextPageNum = config.Pages.Count > 0 ? config.Pages.Max(p => p.PageNumber) + 1 : 1;
|
|
|
|
var newPage = new PageConfig
|
|
{
|
|
PageNumber = nextPageNum,
|
|
PrinterName = _installedPrinters.FirstOrDefault() ?? "",
|
|
TrayNumber = 1
|
|
};
|
|
config.Pages.Add(newPage);
|
|
|
|
LoadPageConfiguration(_selectedDocType);
|
|
}
|
|
|
|
private void RemovePage_Click(object? sender, EventArgs e)
|
|
{
|
|
if (_selectedDocType == null) return;
|
|
|
|
var config = _config.DocumentTypes[_selectedDocType];
|
|
if (config.Pages.Count > 0)
|
|
{
|
|
var lastPage = config.Pages.OrderByDescending(p => p.PageNumber).First();
|
|
config.Pages.Remove(lastPage);
|
|
LoadPageConfiguration(_selectedDocType);
|
|
}
|
|
}
|
|
|
|
private void NewDocType_Click(object? sender, EventArgs e)
|
|
{
|
|
var dialog = new TextInputDialog("New Document Type", "Enter document type name:");
|
|
if (dialog.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(dialog.InputText))
|
|
{
|
|
var docType = dialog.InputText.Trim();
|
|
if (!_config.DocumentTypes.ContainsKey(docType))
|
|
{
|
|
_config.DocumentTypes[docType] = new DocumentTypeConfig { Name = docType };
|
|
LoadDocumentTypes();
|
|
_docTypeListBox.SelectedItem = docType;
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show($"Document type '{docType}' already exists.", "Duplicate", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DeleteDocType_Click(object? sender, EventArgs e)
|
|
{
|
|
if (_selectedDocType == null) return;
|
|
|
|
var result = MessageBox.Show(
|
|
$"Are you sure you want to delete '{_selectedDocType}'?",
|
|
"Confirm Delete",
|
|
MessageBoxButtons.YesNo,
|
|
MessageBoxIcon.Question);
|
|
|
|
if (result == DialogResult.Yes)
|
|
{
|
|
_config.DocumentTypes.Remove(_selectedDocType);
|
|
_selectedDocType = null;
|
|
LoadDocumentTypes();
|
|
_pageConfigPanel.Controls.Clear();
|
|
_configLabel.Text = "Configuration for: (Select a document type)";
|
|
}
|
|
}
|
|
|
|
private void Save_Click(object? sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// Save current page configurations
|
|
if (_selectedDocType != null && _config.DocumentTypes.TryGetValue(_selectedDocType, out var config))
|
|
{
|
|
config.Pages.Clear();
|
|
foreach (var pageControl in _pageControls)
|
|
{
|
|
config.Pages.Add(pageControl.GetPageConfig());
|
|
}
|
|
}
|
|
|
|
bool saveGlobal = _saveGlobalRadio.Checked;
|
|
_configService.Save(_config, saveGlobal);
|
|
|
|
MessageBox.Show(
|
|
$"Configuration saved to {(saveGlobal ? "global" : "local")} file successfully!",
|
|
"Success",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Information);
|
|
|
|
DialogResult = DialogResult.OK;
|
|
Close();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(
|
|
$"Failed to save configuration: {ex.Message}",
|
|
"Error",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Custom control for each page configuration
|
|
public class PageConfigControl : UserControl
|
|
{
|
|
private readonly int _pageNumber;
|
|
private readonly List<string> _printers;
|
|
private readonly ConfigurationService _configService;
|
|
|
|
private ComboBox _printerCombo = null!;
|
|
private ComboBox _trayCombo = null!;
|
|
|
|
public PageConfigControl(int pageNumber, List<string> printers, ConfigurationService configService)
|
|
{
|
|
_pageNumber = pageNumber;
|
|
_printers = printers;
|
|
_configService = configService;
|
|
|
|
InitializeComponent();
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
Size = new Size(560, 60);
|
|
BorderStyle = BorderStyle.FixedSingle;
|
|
|
|
var pageLabel = new Label
|
|
{
|
|
Text = $"Page {_pageNumber}:",
|
|
Location = new Point(10, 10),
|
|
Size = new Size(70, 20),
|
|
Font = new Font(Font, FontStyle.Bold)
|
|
};
|
|
|
|
var printerLabel = new Label
|
|
{
|
|
Text = "Printer:",
|
|
Location = new Point(10, 32),
|
|
Size = new Size(60, 20)
|
|
};
|
|
|
|
_printerCombo = new ComboBox
|
|
{
|
|
Location = new Point(75, 30),
|
|
Size = new Size(250, 25),
|
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|
};
|
|
_printerCombo.Items.AddRange(_printers.ToArray());
|
|
_printerCombo.SelectedIndexChanged += PrinterCombo_SelectedIndexChanged;
|
|
|
|
var trayLabel = new Label
|
|
{
|
|
Text = "Tray:",
|
|
Location = new Point(340, 32),
|
|
Size = new Size(40, 20)
|
|
};
|
|
|
|
_trayCombo = new ComboBox
|
|
{
|
|
Location = new Point(385, 30),
|
|
Size = new Size(165, 25),
|
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|
};
|
|
|
|
Controls.AddRange(new Control[] {
|
|
pageLabel, printerLabel, _printerCombo, trayLabel, _trayCombo
|
|
});
|
|
}
|
|
|
|
public void LoadPage(PageConfig page)
|
|
{
|
|
_printerCombo.SelectedItem = page.PrinterName;
|
|
LoadTrays(page.PrinterName);
|
|
|
|
// Try to find and select the tray
|
|
for (int i = 0; i < _trayCombo.Items.Count; i++)
|
|
{
|
|
if (_trayCombo.Items[i] is TrayItem item && item.TrayNumber == page.TrayNumber)
|
|
{
|
|
_trayCombo.SelectedIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PrinterCombo_SelectedIndexChanged(object? sender, EventArgs e)
|
|
{
|
|
if (_printerCombo.SelectedItem is string printer)
|
|
{
|
|
LoadTrays(printer);
|
|
}
|
|
}
|
|
|
|
private void LoadTrays(string printerName)
|
|
{
|
|
_trayCombo.Items.Clear();
|
|
var trays = _configService.GetPrinterTrays(printerName);
|
|
foreach (var (number, name) in trays)
|
|
{
|
|
_trayCombo.Items.Add(new TrayItem { TrayNumber = number, TrayName = name });
|
|
}
|
|
if (_trayCombo.Items.Count > 0)
|
|
{
|
|
_trayCombo.SelectedIndex = 0;
|
|
}
|
|
}
|
|
|
|
public PageConfig GetPageConfig()
|
|
{
|
|
var selectedTray = _trayCombo.SelectedItem as TrayItem;
|
|
return new PageConfig
|
|
{
|
|
PageNumber = _pageNumber,
|
|
PrinterName = _printerCombo.SelectedItem?.ToString() ?? "",
|
|
TrayNumber = selectedTray?.TrayNumber ?? 1,
|
|
TrayLabel = selectedTray?.TrayName
|
|
};
|
|
}
|
|
|
|
private class TrayItem
|
|
{
|
|
public int TrayNumber { get; set; }
|
|
public string TrayName { get; set; } = "";
|
|
|
|
public override string ToString() => $"Tray {TrayNumber} - {TrayName}";
|
|
}
|
|
}
|
|
|
|
// Simple text input dialog
|
|
public class TextInputDialog : Form
|
|
{
|
|
private TextBox _textBox = null!;
|
|
public string InputText => _textBox.Text;
|
|
|
|
public TextInputDialog(string title, string prompt)
|
|
{
|
|
Text = title;
|
|
Size = new Size(400, 150);
|
|
StartPosition = FormStartPosition.CenterParent;
|
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
|
MaximizeBox = false;
|
|
MinimizeBox = false;
|
|
|
|
var promptLabel = new Label
|
|
{
|
|
Text = prompt,
|
|
Location = new Point(20, 20),
|
|
Size = new Size(360, 20)
|
|
};
|
|
|
|
_textBox = new TextBox
|
|
{
|
|
Location = new Point(20, 50),
|
|
Size = new Size(360, 25)
|
|
};
|
|
|
|
var okButton = new Button
|
|
{
|
|
Text = "OK",
|
|
DialogResult = DialogResult.OK,
|
|
Location = new Point(220, 85),
|
|
Size = new Size(75, 30)
|
|
};
|
|
|
|
var cancelButton = new Button
|
|
{
|
|
Text = "Cancel",
|
|
DialogResult = DialogResult.Cancel,
|
|
Location = new Point(305, 85),
|
|
Size = new Size(75, 30)
|
|
};
|
|
|
|
AcceptButton = okButton;
|
|
CancelButton = cancelButton;
|
|
|
|
Controls.AddRange(new Control[] { promptLabel, _textBox, okButton, cancelButton });
|
|
}
|
|
}
|