feat: restore p-rec-annot manual annotation palette
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
namespace PRecAnnot.Core;
|
||||
|
||||
public enum ManualAnnotationKind
|
||||
{
|
||||
LineNumber,
|
||||
ValveOrNozzle,
|
||||
FlowDirection,
|
||||
InstrumentPosition,
|
||||
SectionElevation,
|
||||
InstrumentConnection,
|
||||
AutoCadBlock,
|
||||
PlatformElevation,
|
||||
OtherElevation
|
||||
}
|
||||
|
||||
public static class ManualAnnotationCommandRouter
|
||||
{
|
||||
public static string Resolve(ManualAnnotationKind kind) => kind switch
|
||||
{
|
||||
ManualAnnotationKind.LineNumber => "PXP-LN",
|
||||
ManualAnnotationKind.FlowDirection => "PXP-OA",
|
||||
ManualAnnotationKind.SectionElevation or ManualAnnotationKind.PlatformElevation or ManualAnnotationKind.OtherElevation => "PXP-IE",
|
||||
ManualAnnotationKind.AutoCadBlock => "PXP-MAB",
|
||||
ManualAnnotationKind.ValveOrNozzle or ManualAnnotationKind.InstrumentPosition or ManualAnnotationKind.InstrumentConnection => "PXP-AAV",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(kind), kind, "Unknown manual annotation kind.")
|
||||
};
|
||||
}
|
||||
@@ -19,6 +19,7 @@ public sealed class EntryPoint : IExtensionApplication
|
||||
RuntimeDiagnostics.Write("CompositeModulesValidated", resultStatus: "Validated", details: new Dictionary<string, object?> { ["PackageVersion"] = manifest.Version, ["ModuleCount"] = manifest.Modules.Count });
|
||||
RibbonIntegration.Register();
|
||||
SwapAttributesContextMenu.Attach();
|
||||
ManualAnnotationPalette.Initialize();
|
||||
// Test automation is driven only by the explicitly generated /b script.
|
||||
// Initialize remains production-equivalent and must not orchestrate commands.
|
||||
RuntimeDiagnostics.Write("AssemblyInitializeCompleted");
|
||||
@@ -29,6 +30,7 @@ public sealed class EntryPoint : IExtensionApplication
|
||||
RuntimeDiagnostics.Write("AssemblyTerminateStarted");
|
||||
RibbonIntegration.Terminate();
|
||||
SwapAttributesContextMenu.Detach();
|
||||
ManualAnnotationPalette.Terminate();
|
||||
RuntimeDiagnostics.Write("AssemblyTerminateCompleted");
|
||||
}
|
||||
|
||||
@@ -53,6 +55,10 @@ public sealed class EntryPoint : IExtensionApplication
|
||||
[CommandMethod("PXP-UOB")] public void UpdateOrthoViewBlocksCommand() => PRecAnnot.Plant3D2026.UpdateOrthoViewBlocksCommand.Run();
|
||||
[CommandMethod("PXP-AC", CommandFlags.UsePickSet)] public void SwapAttributesCommand() => PRecAnnot.Plant3D2026.SwapAttributesCommand.Run();
|
||||
[CommandMethod("PXP-IOD", CommandFlags.Session)] public void UpdateOrthoDrawingsCommand() => PRecAnnot.Plant3D2026.UpdateOrthoDrawingsCommand.Run();
|
||||
[CommandMethod("mto-ma")] public void ShowManualAnnotationPaletteCommand() => ManualAnnotationPalette.Show();
|
||||
[CommandMethod("PXP-MA")] public void ShowManualAnnotationPaletteAliasCommand() => ManualAnnotationPalette.Show();
|
||||
[CommandMethod("CAC1")] public void PlaceManualAnnotationCommand() => ManualAnnotationPalette.PlaceSelected();
|
||||
[CommandMethod("PXP-MAB")] public void InsertManualBlockCommand() => ManualBlockInsertionCommand.Run();
|
||||
|
||||
[CommandMethod("PHP_REC_AUTOMATION_START", CommandFlags.Session)]
|
||||
public void AutomationStartCommand() => FirstLimitedApplyAutomationBootstrap.Arm();
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.EditorInput;
|
||||
using Autodesk.AutoCAD.Geometry;
|
||||
using Autodesk.AutoCAD.Windows;
|
||||
using Autodesk.ProcessPower.PlantInstance;
|
||||
using PRecAnnot.Core;
|
||||
using WinForms = System.Windows.Forms;
|
||||
using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
|
||||
|
||||
namespace PRecAnnot.Plant3D2026;
|
||||
|
||||
internal static class ManualAnnotationPalette
|
||||
{
|
||||
private static readonly Guid PaletteId = new("dc74a715-60cc-6f6b-8dc7-ccf6a3e52d60");
|
||||
private static PaletteSet? palette;
|
||||
private static ManualAnnotationControl? control;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
AcadApplication.DocumentManager.DocumentActivated -= DocumentActivated;
|
||||
AcadApplication.DocumentManager.DocumentActivated += DocumentActivated;
|
||||
}
|
||||
public static void Terminate()
|
||||
{
|
||||
AcadApplication.DocumentManager.DocumentActivated -= DocumentActivated;
|
||||
if (palette is not null) palette.Visible = false;
|
||||
}
|
||||
public static void Show()
|
||||
{
|
||||
if (palette is null)
|
||||
{
|
||||
control = new ManualAnnotationControl();
|
||||
palette = new PaletteSet("Ortho drawing annotations", "P_REC_ANNOT_MANUAL", PaletteId)
|
||||
{ Style = PaletteSetStyles.NameEditable | PaletteSetStyles.ShowPropertiesMenu | PaletteSetStyles.ShowAutoHideButton | PaletteSetStyles.ShowCloseButton };
|
||||
palette.Add("Annotations", control);
|
||||
}
|
||||
control!.RefreshAvailability(); palette.Visible = true;
|
||||
RuntimeDiagnostics.Write("ManualAnnotationPaletteShown", resultStatus: "Visible");
|
||||
}
|
||||
public static void PlaceSelected() => control?.Place();
|
||||
private static void DocumentActivated(object sender, Autodesk.AutoCAD.ApplicationServices.DocumentCollectionEventArgs args) => control?.RefreshAvailability();
|
||||
}
|
||||
|
||||
internal sealed class ManualAnnotationControl : WinForms.UserControl
|
||||
{
|
||||
private readonly WinForms.FlowLayoutPanel choices = new() { Dock = WinForms.DockStyle.Top, AutoSize = true, FlowDirection = WinForms.FlowDirection.TopDown, WrapContents = false };
|
||||
private readonly WinForms.Button place = new() { Text = "Place", AutoSize = true };
|
||||
private readonly WinForms.Button reconnect = new() { Text = "Reconnect / refresh", AutoSize = true };
|
||||
private readonly WinForms.Button help = new() { Text = "Help", AutoSize = true };
|
||||
private readonly Dictionary<WinForms.RadioButton, ManualAnnotationKind> kinds = new();
|
||||
public ManualAnnotationControl()
|
||||
{
|
||||
Dock = WinForms.DockStyle.Fill; AutoScroll = true;
|
||||
Add("Line number", ManualAnnotationKind.LineNumber, true); Add("Valve or nozzle", ManualAnnotationKind.ValveOrNozzle); Add("Flow direction", ManualAnnotationKind.FlowDirection);
|
||||
Add("Instrument position", ManualAnnotationKind.InstrumentPosition); Add("Section elevation", ManualAnnotationKind.SectionElevation); Add("Instrument connection point", ManualAnnotationKind.InstrumentConnection);
|
||||
Add("AutoCAD block", ManualAnnotationKind.AutoCadBlock); Add("Platform elevation", ManualAnnotationKind.PlatformElevation); Add("Other elevation", ManualAnnotationKind.OtherElevation);
|
||||
place.Click += (_, _) => Place(); reconnect.Click += (_, _) => Reconnect(); help.Click += (_, _) => OpenHelp();
|
||||
var actions = new WinForms.FlowLayoutPanel { Dock = WinForms.DockStyle.Top, AutoSize = true }; actions.Controls.Add(place); actions.Controls.Add(reconnect); actions.Controls.Add(help);
|
||||
Controls.Add(actions); Controls.Add(choices); RefreshTheme();
|
||||
}
|
||||
private void Add(string text, ManualAnnotationKind kind, bool selected = false) { var button = new WinForms.RadioButton { Text = text, AutoSize = true, Checked = selected }; kinds.Add(button, kind); choices.Controls.Add(button); }
|
||||
public void RefreshAvailability() { var available = AcadApplication.DocumentManager.MdiActiveDocument is not null && PlantApplication.CurrentProject is not null; place.Enabled = available; reconnect.Enabled = available; RefreshTheme(); }
|
||||
public void Place()
|
||||
{
|
||||
var document = AcadApplication.DocumentManager.MdiActiveDocument; if (document is null) return;
|
||||
var kind = kinds.First(value => value.Key.Checked).Value;
|
||||
var command = ManualAnnotationCommandRouter.Resolve(kind);
|
||||
document.SendStringToExecute(command + " ", true, false, false);
|
||||
RuntimeDiagnostics.Write("ManualAnnotationActionInvoked", commandName: command, resultStatus: kind.ToString(), document: document);
|
||||
}
|
||||
private static void Reconnect() => AcadApplication.DocumentManager.MdiActiveDocument?.SendStringToExecute("PXP-ULN ", true, false, false);
|
||||
private static void OpenHelp()
|
||||
{
|
||||
var path = Path.Combine(Path.GetDirectoryName(typeof(ManualAnnotationControl).Assembly.Location)!, "ManualAnnotationHelp.pdf");
|
||||
if (File.Exists(path)) System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(path) { UseShellExecute = true });
|
||||
}
|
||||
private void RefreshTheme()
|
||||
{
|
||||
var dark = Convert.ToInt16(AcadApplication.GetSystemVariable("COLORTHEME")) == 0;
|
||||
BackColor = dark ? System.Drawing.Color.FromArgb(92, 92, 92) : System.Drawing.Color.FromArgb(245, 245, 245); ForeColor = dark ? System.Drawing.Color.White : System.Drawing.Color.Black;
|
||||
foreach (WinForms.Control child in choices.Controls) { child.BackColor = BackColor; child.ForeColor = ForeColor; }
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ManualBlockInsertionCommand
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
var document = AcadApplication.DocumentManager.MdiActiveDocument; if (document is null) return;
|
||||
var name = document.Editor.GetString(new PromptStringOptions("\nBlock name: ") { AllowSpaces = true }); if (name.Status != PromptStatus.OK || string.IsNullOrWhiteSpace(name.StringResult)) return;
|
||||
var point = document.Editor.GetPoint("\nInsertion point: "); if (point.Status != PromptStatus.OK) return;
|
||||
var angle = document.Editor.GetAngle(new PromptAngleOptions("\nRotation <0>: ") { AllowNone = true, BasePoint = point.Value, UseBasePoint = true }); if (angle.Status is not (PromptStatus.OK or PromptStatus.None)) return;
|
||||
using var documentLock = document.LockDocument(); using var transaction = document.Database.TransactionManager.StartTransaction();
|
||||
var blocks = (BlockTable)transaction.GetObject(document.Database.BlockTableId, OpenMode.ForRead); if (!blocks.Has(name.StringResult)) { document.Editor.WriteMessage("\nBlock definition not found."); return; }
|
||||
var space = (BlockTableRecord)transaction.GetObject(document.Database.CurrentSpaceId, OpenMode.ForWrite); var definition = (BlockTableRecord)transaction.GetObject(blocks[name.StringResult], OpenMode.ForRead);
|
||||
using var reference = new BlockReference(point.Value, definition.ObjectId) { Rotation = angle.Status == PromptStatus.OK ? angle.Value : 0 }; space.AppendEntity(reference); transaction.AddNewlyCreatedDBObject(reference, true);
|
||||
foreach (ObjectId id in definition)
|
||||
if (transaction.GetObject(id, OpenMode.ForRead) is AttributeDefinition source && !source.Constant)
|
||||
{ var value = document.Editor.GetString(new PromptStringOptions($"\n{source.Tag} <{source.TextString}>: ") { AllowSpaces = true }); using var attribute = new AttributeReference(); attribute.SetAttributeFromBlock(source, reference.BlockTransform); attribute.TextString = value.Status == PromptStatus.OK ? value.StringResult : source.TextString; reference.AttributeCollection.AppendAttribute(attribute); transaction.AddNewlyCreatedDBObject(attribute, true); }
|
||||
transaction.Commit(); document.Editor.WriteMessage("\nManual block placed; AutoCAD UNDO is available.");
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using PRecAnnot.Core;
|
||||
|
||||
namespace PRecAnnot.Core.Tests;
|
||||
|
||||
public sealed class ManualAnnotationCommandRouterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(ManualAnnotationKind.LineNumber, "PXP-LN")]
|
||||
[InlineData(ManualAnnotationKind.ValveOrNozzle, "PXP-AAV")]
|
||||
[InlineData(ManualAnnotationKind.FlowDirection, "PXP-OA")]
|
||||
[InlineData(ManualAnnotationKind.InstrumentPosition, "PXP-AAV")]
|
||||
[InlineData(ManualAnnotationKind.SectionElevation, "PXP-IE")]
|
||||
[InlineData(ManualAnnotationKind.InstrumentConnection, "PXP-AAV")]
|
||||
[InlineData(ManualAnnotationKind.AutoCadBlock, "PXP-MAB")]
|
||||
[InlineData(ManualAnnotationKind.PlatformElevation, "PXP-IE")]
|
||||
[InlineData(ManualAnnotationKind.OtherElevation, "PXP-IE")]
|
||||
public void Resolve_routes_every_legacy_palette_choice(ManualAnnotationKind kind, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ManualAnnotationCommandRouter.Resolve(kind));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user