This very interesting feature came to my attention via an internal discussion. Thanks, once again, to George Varghese for providing the base sample used for this post.
At various times inside AutoCAD – such as when a block is selected, for instance – a specific ribbon tab is displayed “contextually”. As an example, when you select a Hatch object inside the AutoCAD editor, you should see a hatch-related contextual tab displayed:
It’s possible to implement your own, comparable behaviour inside the AutoCAD editor using a combination of a simple .NET module, a XAML file and some CUI editing (or a partial CUI file).
Let’s start with the .NET module. Here’s some code that implements a sample rule that can be hooked into AutoCAD to tell it when a certain condition has been satisfied. In our case, the condition we want is that exactly two circles are selected in the drawing editor.
Here’s the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
namespace Rules
{
public class SampleRule
{
// The flag stating whether the contextual tab is enabled
bool _enableCtxtTab = false;
// A static reference to the rule itself
static SampleRule _rule = null;
// A public property referenced from the XAML, getting
// whether the contextual tab should be enabled
public bool TwoCirclesSelected
{
get { return _enableCtxtTab; }
}
// A public static property providing access to the rule
// (also referenced from the XAML)
public static SampleRule TheRule
{
get
{
if (_rule == null)
_rule = new SampleRule();
return _rule;
}
}
// Constructor for the rule, where we attach various
// even handlers
SampleRule()
{
DocumentCollection dm =
Autodesk.AutoCAD.ApplicationServices.Application.
DocumentManager;
dm.DocumentCreated +=
new DocumentCollectionEventHandler(
OnDocumentCreated
);
dm.DocumentToBeDestroyed +=
new DocumentCollectionEventHandler(
OnDocumentToBeDestroyed
);
dm.MdiActiveDocument.ImpliedSelectionChanged +=
new EventHandler(
OnImpliedSelectionChanged
);
}
// When the pickfirst selection is changed, check
// the selection to see whether to enable the
// contextual tab (if exactly two circles are selected)
void OnImpliedSelectionChanged(object sender, EventArgs e)
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
PromptSelectionResult res = ed.SelectImplied();
if (res == null)
return;
EnableContextualTab(res.Value);
}
// When a document is created, add our handler to it
void OnDocumentCreated(
object sender, DocumentCollectionEventArgs e
)
{
e.Document.ImpliedSelectionChanged +=
new EventHandler(OnImpliedSelectionChanged);
}
// When a document is destroyed, remove our handler from it
void OnDocumentToBeDestroyed(
object sender, DocumentCollectionEventArgs e
)
{
e.Document.ImpliedSelectionChanged -=
new EventHandler(OnImpliedSelectionChanged);
}
// Check whether we should enable the contextual tab,
// based on the selection passed in
void EnableContextualTab(SelectionSet ss)
{
// The default assumption is "no"
_enableCtxtTab = false;
// We need to have exactly two objects selected
if (ss == null)
return;
if (ss.Count == 2)
{
ObjectId[] ids = ss.GetObjectIds();
if (ids != null)
{
Database db =
HostApplicationServices.WorkingDatabase;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
// Check whether both objects are Circles
DBObject obj =
tr.GetObject(ids[0], OpenMode.ForRead);
DBObject obj2 =
tr.GetObject(ids[1], OpenMode.ForRead);
_enableCtxtTab = (obj is Circle && obj2 is Circle);
// Commit, as it's quicker than aborting
tr.Commit();
}
}
}
}
}
}
The above code is reasonably simple – it detects changes to the pickfirst selection set and checks whether it contains exactly two objects, both of which are circles. If so, it sets a Boolean property that can be checked by AutoCAD.
To tell AutoCAD what to do with the module, we need to include a small XAML file which AutoCAD will parse on startup:
<?xml version="1.0" encoding="utf-8"?>
<TabSelectorRules
xmlns="clr-namespace:Autodesk.AutoCAD.Ribbon;assembly=AcWindows"
Ordering="0">
<TabSelectorRules.References>
<AssemblyReference
Namespace="Rules"
Assembly="ADNPlugin-SampleRule"/>
</TabSelectorRules.References>
<Rule
Uid="ADNPluginSampleRuleId"
DisplayName="Sample: Two circles selected rule"
Theme="Green"
Trigger="Selection">
<![CDATA[
SampleRule.TheRule.TwoCirclesSelected
]]>
</Rule>
</TabSelectorRules>
The DLL and XAML files are to be placed in the AutoCAD executable folder (on my system this is “C:\Program Files\Autodesk\AutoCAD 2012 - English”), which means it’s imperative you prefix both with your Registered Developer Symbol (RDS), obtainable from http://autodesk.com/symbolreg.
In my case – as I have the ADNP symbol registered – I’ve named the files ADNPlugin-SampleRule.dll and ADNPlugin-SampleContextualTabSelectorRules.xaml. You can find them here, along with the source project.
Now on to actually using the rule inside AutoCAD.
Launch AutoCAD: if all is well you should see nothing out of the ordinary, otherwise you’ll see lots of additional (and often very helpful) text describing the problem with your rule implementation (or its XAML description).
Run the CUI command. From here you should see a new node named “Sample: Two circles selected rule” under Ribbon –> Contextual Tab States.
To have a custom tab displayed when this condition is true, simply drag and drop the tab from the Ribbon –> Tabs list to our new node. You’ll see a number of tabs named “… Contextual Tab”, for just this purpose. Just for fun – and because we can – let’s show the “Solid Modeling” tab when two circles are selected in the editor.
Sure enough, when we close the CUI dialog, saving changes, and select two circles in the AutoCAD editor, we see the Solid Modeling tab gets displayed and highlighted with our chosen theme (a green tint to it):
Now of course it’s unlikely you’ll want to do something quite like this, but this sample does show how you might implement your own contextual tabs, and not just for objects of a certain – you can perform quite deep analysis of the selection set, should you so wish (keeping an eye on interactive performance, of course).