sources/Google.Solutions.Terminal/Controls/ClientDiagnosticsWindow.cs (101 lines of code) (raw):
//
// Copyright 2024 Google LLC
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
using Google.Solutions.Common.Util;
using Google.Solutions.Mvvm.Binding;
using Google.Solutions.Mvvm.Binding.Commands;
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace Google.Solutions.Terminal.Controls
{
/// <summary>
/// Simple window that shows a client and its properties.
///
/// For testing only.
/// </summary>
public class ClientDiagnosticsWindow<TClient> : Form
where TClient : ClientBase
{
public TClient Client { get; }
public ToolStripMenuItem ClientMenu { get; }
private void ShowError(string caption, Exception e)
{
MessageBox.Show(
this,
e.FullMessage(),
caption,
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
}
public ClientDiagnosticsWindow(TClient client)
{
this.Client = client;
if (client is RdpClient rdpClient)
{
rdpClient.MainWindow = this;
}
SuspendLayout();
this.AutoScaleDimensions = new System.Drawing.SizeF(96, 96);
this.AutoScaleMode = AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(1400, 1000);
this.Text = typeof(TClient).Name;
//
// Split container.
//
var splitContainer = new SplitContainer()
{
Dock = DockStyle.Fill,
SplitterDistance = 450
};
splitContainer.BeginInit();
this.Controls.Add(splitContainer);
//
// Client.
//
client.Dock = DockStyle.Fill;
splitContainer.Panel1.Controls.Add(client);
client.Bind(new ClientBindingContext());
//
// PropertyGrid.
//
var propertyGrid = new PropertyGrid()
{
Dock = DockStyle.Fill,
SelectedObject = client,
};
splitContainer.Panel2.Controls.Add(propertyGrid);
//
// Main menu.
//
var menu = new MenuStrip();
this.MainMenuStrip = menu;
this.Controls.Add(menu);
this.ClientMenu = new ToolStripMenuItem("&Client");
menu.Items.Add(this.ClientMenu);
//
// Add menu item for each public parameter-less method.
//
foreach (var method in client.GetType()
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(m => typeof(ClientBase).IsAssignableFrom(m.DeclaringType))
.Where(m => !m.IsSpecialName)
.Where(m => !m.GetParameters().Any()))
{
this.ClientMenu.DropDownItems.Add(method.Name).Click += (_, __) =>
{
try
{
method.Invoke(client, null);
}
catch (Exception e)
{
ShowError("The command failed", e);
}
};
}
splitContainer.EndInit();
ResumeLayout(false);
client.ConnectionFailed += (_, args)
=> ShowError("Connection failed", args.Exception);
}
private class ClientBindingContext : IBindingContext
{
public void OnBindingCreated(
IComponent control,
IDisposable binding)
{
}
public void OnCommandExecuted(
ICommandBase command)
{
}
public void OnCommandFailed(
IWin32Window? window,
ICommandBase command,
Exception exception)
{
}
}
}
}