Method parameters – overview

Syntax of C# enables multitude of way how to pass parameters into a method. The most basic way is to provide a parameter type and name. This will enforce that whenever this method is called this parameter must be supplied and the method will produce a result based on that. However this is not the only way, and surprisingly (at least for beginners) C# offers quite wide range of customisation of method signatures.

Optional parameter
A parameter can be optional, and in case it is not passed in a call its default value will be used.

In this case there are two things to be aware of:
i) optional parameters must be at the end, any other parameter cannot be after optional (a compiler will not allow that);
ii) if a method with more than one optional parameter is called the order of them matters, so in the example above if first optional parameter is to be provided, the second is to be omitted the you simply call the method without the last one which will take its default value:

However if one wish to provide only second parameter and use default value of the first optional parameter one must pass it as named parameter:


Reference parameters
In .NET there is distinction between value types and reference types [more]. So generally objects are passed by reference (as they are reference types), primitive types are passed by value (as they are value types, as well as structs). This means, in simple words, that changes a method do to an object will be visible outside. That doesn’t happen to a value type. The ref keyword allows us to declare in method’s signature that a parameter is to be passed by reference (even if it’s a value type).

Let’s consider the above code: if the RefParam() is to be called it will expect a reference to an integer variable which will be modified inside the method and saved to a reference. It will not accept hard-coded value. Note that the ref keyword needs to be present in both: method’s declaration and method’s call.

The above code will output value of n variable which is now increased by the RefParam() method.

There are two more ways to pass a parameter by reference: the in and out keywords. The former enforces that the parameter is not modified inside a method, the latter enforces that the parameter is set inside the method.

So as you can see a compiler will not allow any code that would potentially change value of reference parameter with in keyword. The advantage is that since it is passed by reference it will not be boxed (performance advantage) and you can clearly state at design that this parameter is not to be modified but read-only. Note that the in keyword is available in C# 7.2.

In a method which one parameter is declared as out there must be a statement that would set its value. If not a compiler would generate an error. In this case (similarly as with the in keyowrd) we have this explicit declaration that in the method we need to modify value of a parameter. Another advantage is that we can new-up a variable when a method is called:

This may be used as a way return more that one value by a method [more].

Multiple parameters of the same type
In case we want to pass unknown number of parameters of the same type we can use the params keyword.

If we want the above to work we could declare an overloaded method, however using the params keyword makes it way easier.

However, in this case we need to remember that type of this parameter must be an array (one dimensional, compiler won’t allow anything else) and it must be declared as the last parameter in a method’s signature.

That is short overview how flexible declaring a method can be. I encourage to experiment with it to get comfortable with all the possibilities C# language offers in this matter.

I’m back and Git – rookie’s thoughts

Hello there!
It’s certainly been a while since my last post! It was more or less 6 months ago which is a long time but I wasn’t idle, oh no! If you briefly scan all my posts you’ll notice that my field of interests was Windows apps, mostly WPF technology and MVVM pattern. However this has recently changed – I’ve started ASP.NET app! The project is a web app for acquainted company which purpose is to organise and keep track of service jobs they provide to their client. It is not an open project so I can’t share the code at the moment. Let me say only that it is an MVC app using what comes by default with an MVC template in Visual Studio (Entity Framework, Identity, bootstrap, jQuery etc.) so as you can see a lot of new things!

Here you go a screenshot of the early version of the current app (first version is up and running, but it is very very basic so they have anything to start with). Let me stop here about this project and let’s move on to the next thing which is:

Git – my first thoughts

So, I’ve already been using GitHub (here’s my account) but recently I did a quick course on Git (on LinkedIn Learning [link]) so I thought why not to try it on my own. So I downloaded packages, created separate partition on my hard drive and installed it and started using it. As I’m a beginner I use only some basic commands that you definitely know:

  • git status – shows current changes and what’s been staged
  • git add .  – adds all changes to commit stage, the dot indicates that all files must be added, you could replace it by a specific file name
  • git commit -m”<message>” – commits staged changes to a repository with a message, I generally try to always commit with a message
  • git commit -am”<message>” – adds to stage all changes (except new files) and commits them to a repository
  • git log –x – prints out a log of a commit where x is an ordinal number of a commit (1 – is the newest)
  • git push – pushes (uploads) all commits to a remote repository

And that’s more or less it. That’s enough for me to start.
Now, a word about remote repository. You can use GitHub to host your remote repositories, they offer unlimited number but in a free plan they can only be public repositories (it’s easy to find how to set it all up on their help pages). If you’re looking for a private repo you can simply use your local drive (once you have a directory set up simply run git bash, navigate to this directory and execute git init, or start your project in Visual Studio and tick the Create new Git repository option). However if you still need the remote repository to push your commits (for instance to share the source code with others working with you on a project, or for backup) what you can do is to use Visual Studio Team Services . They offer private repositories. To set a remote address for your repo in VSTS you need to:
a) once you are registered and logged to VSTS you need to create new project with version control set to Git
b) go to https://xxx.visualstudio.com/_projects where xxx is your alias and click on your project’s name, this will bring you to project’s homepage
c) unfold second category as below
d) execute the above commands in your git bash (of course your URL will differ)

It’s all set! This basically links your local repo with a remote repo at VSTS. In the above command ‘origin’ is a name for the remote repo. If your case is that you use only one remote repository you don’t need to specify it when executing the push command in future.
So, that’s about it what I wanted to say about my first steps with git. Maybe as a side note I’d add that help files that come together with git installation are really really helpful so I encourage to look for solution there in case you encounter any problem.

One-bytes #2: Selection in WPF, OnPropertyChanged parameters

*** #2.1 Item selection in WPF selector-enabled items control***
In WPF we can use multiple types of controls to display collections of items which allow user to select one or multiple items from the collection. In this post I’m going to discuss what single selection possibilities they offer.
Let’s start with inheritance hierarchy – controls that allow such selection inherit from System.Windows.Controls.Primitives.Selector. If we take a look at what properties they have we find four that may be involved in selection process:

  •  SelectedIndex – Gets or sets the index of the first item in the current selection or returns negative one (-1) if the selection is empty.
  • SelectedItem – Gets or sets the first item in the current selection or returns null if the selection is empty
  • SelectedValue – Gets or sets the value of the SelectedItem, obtained by using SelectedValuePath.
  • SelectedValuePath – Gets or sets the path that is used to get the SelectedValue from the SelectedItem.
    source: msdn.microsoft.com

So, there are three ways get the selected item: i) its integer index in the collection, ii) the item itself, iii) one desired value from the item. 
I have prepared a quick demo to show that. The app displays a ListBox of custom class objects and once an item is selected displays all three ways to present the selection. Let’s take a look into the code, starting with the class of objects that our list will contain:

The list will be generated and stored in view model. The view model will also have three public properties: i) ItemSelectedIndex of type integer bound to SelectedIndex property of  our ListBox, ii) ItemSelectedItem of type Item bound to SelectedItem, iii) ItemSelectedValue of type string bound to SelectedValue. Let’s take a look at complete ViewModel class:

And now the most important part – the view. As mentioned above as a container for collection we will use ListBox and bound properties as it was described when discussing the view model class. The only thing that’s left is setting correct value to SelectedValuePath property. In this case we want to use Name property of our item class so we need to set SelectedValuePath to “Name”. Here’s how to set the ListBox up:

Now, to use the selected index, item or value which are bound to corresponding properties in view model we need to add some controls and again bound them to view model properties:

And that’s it. To sum things up – there are three ways to access selected item in a selector control in WPF: by its index, by the item itself or by one particular value in the item.

*** #2.2 Passing property name to OnPropertyChanged()***
Second thing I want to mention today is a hint how to make invoking OnPropertyChanged() method in a property setter a bit more controlled when not using any MVVM framework.
ViewModels usually implement INotifyPropertyChanged interface which purpose is to notify views when a property has been updated. This is done by invoking OnPropertyChanged method with property name passed as a parameter.

That is not the best way. What if we decide to change the property name and the backing field can also be changed somewhere else? In this case we need to go and manually change the hard-coded property name. So what can be done instead is this:

Having passed the parameter this way we can simply go to the property, right click and rename it using Visual Studio renaming tool which will update all calls to this property. Definitely better!

Design Patterns #9: Composite

Design patterns episode 9 – Composite

With unexpected delay but patterns are back! In this episode – composite.

The composite is generally used to model tree-like structures in a way that classes that are using the composite can handle its elements in one particular way without having to distinguish whether an element has children – a composite, or hasn’t – a leaf (in other words, whether we can go further down the tree or element is a dead-end).

The first thing that comes up when thinking about that kind of structure would be a directory tree where folders are composites and files are leafs. Or any other structure alike: corporate structure (managers and subordinates), online shops (categories and concrete items) and many many more.

DEFINITION
Let’s see how the Head First book defines this pattern:

The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets client treat individual objects and composition of objects uniformly.
(Freeman, Eric, et al. Head First Design Patterns. O’Reilly Media, Inc. 2004) 

So, in other words we have tree structure of objects and collection of objects and the client doesn’t need to care about if it’s a leaf or a composite. This is the key feature of this pattern. For instance, let’s think about file system where we have files and directories. Both of them are elements of file system and should be treated the same: the client can perform the same operations on both – rename, delete, get size etc. But obviously we can do more things with directories (as this is a collection of files and directories), therefore composite pattern isn’t applicable here (of course you could use typecasting to make it work but that’s a different thing).
The diagram shows what discussed above – both concretions are treated the same, nothing different can client do with one or the other type. The diagram presented here is different than what’s in the book. The book adds further methods: add()remove(),  getChild(). But isn’t that inconsistent with the definition? How can you add a further child to a leaf? You could throw an exception but wouldn’t that violate the Interface Segregation Principle? That kind of issues have been greatly discussed here by the guy who I quoted on multiple occasions.
So, to conclude this aspect of the pattern – my opinion is that we should stick to ISP and not force any class to implement something that the class doesn’t use. Period. Let’s move on to code example.

EXAMPLE

In our code example we’re going to build a store’s menu. Let’s start with the abstraction:

Our IStoreElement consist of name property and a method to list self in the menu: there will be different implementations of this method for leaves and composites. This method can take optional argument as we want to nicely format the menu by indentation of sub-components.
Now the leaf class:

Leaf’s implementation of ListOut() method works that it returns a string with given number of dashes and its name.
And finally composite class:

This class is equipped with private list of objects that implement our base interface. This list can be set in constructor.
The ListOut() method starts with the same thing that counterparting method in leaves but before returning the value recursively invokes the same method for all IStoreElements that the composite holds in its private list. This invocation takes indent parameter increased by 1. This way we achieve that nice formatting of the list once requested in the topmost component.
Now, let’s see how it work all together:

We generate the list and then print to the console the string returned by ListOut().

To sum things up: he Composite Pattern is used to represent tree-like structures where all their elements can be treated uniformly, where single components are called leaves and collections of components are called composites. The pattern can be equipped with methods to modify the content but this lead to violation of Interface Segregation Principle.

Next week: the State Pattern. I hope that this time without any delay. Check the links and source code below. Thank you!

Composite pattern by Christopher Okhravi: link [YouTube]
Composite vs. Decorator by Christopher Okhravi: link [YouTube]
Composite pattern by Michael: link [YouTube]
Source code: TXT file

User-defined value type

Hello there!
Something basic today: how to write your own value type. In C# we distinguish two kinds of data type: value type and reference type. The former is a) stored on stack, b) is by default it is passed as an argument by value; the latter is a) stored on heap and only its address is stored on stack, b) is passed as an argument by reference. At this stage the important thing that is needed to know is that point a makes impact on performance [more]; point b makes impact of how data is circulating through methods. If an argument is passed by value only the value will be taken into the method and, we may say, the link between variable name and its value will be gone from method’s point of view, this means that the original variable cannot be modified by the method. If an argument is passed by reference that link will still be valid meaning that whatever changes a method do to the data it will be reflected everywhere that data is used. The code below will make it much clearer:

The output of the above would be:
As you can see modifications to our list of strings which is a reference type have been done to our object, however our integer variable which is a value type have not changed because only its value was passed to the method. That’s the main difference. The good thing to know is that value types can also be passed by reference – to do that we use keyword ref before an argument we want to pass by reference. This keyword must be present both in method signature and in its invocation place.

And the result:
So, that explanation is enough. We know what is the difference between value and reference type and what implication does that difference bring to behaviour of these types. Now, let’s move on to our custom value type. These are basically structs. They (similarly to classes) can consist of fields, properties, methods etc. and struct’s members can be static, but the struct itself cannot be static. Another important feature is that a struct cannon be derived from a class (that’s obvious) or another struct, however they can implement interfaces.

Our value type will store coordinates assuming that point 0,0 is the bottom left corner of our plane – this means that only positive values of component X and component Y can be assigned. This is due to way of how our value type will be assigned:

So, let’s start with required properties for X and Y coordinates, and distance from point 0,0. That’s simple:

Now, time for constructor. What it is actually going to do is decomposition into two coordinate component. It is also going to be private as we won’t be creating variables of this type using the constructor but simply by assigning a double.

This decomposition is achieved by using some of the static methods of Math class [see here].

Now, the fun part: how to make it possible to assign double value to our struct using ‘=’ operator? Simply by defining new implicit conversion operator that will use already defined private constructor to create an instance of our struct.

Next step would be to override three methods: ToString(), GetHashCode() and Equals() methods. A word of explanation here: although a struct is a value type it is derived from ValueType type, which in turn is derived from Object, and despite the fact that it is not necessary to override those three methods we want to be sure that they will act as we intend: ToString() will return X and Y components separated by comma, GetHashCode() will return hash code for double created based on X and Y, and Equals will check if the argument is of our user-defined type and if it does the method will compare X components and Y components:

And now we’re at the point where we could stop. Having the above done is enough to use our struct but we want to override some of the operators to make it easier to use. We will override pair ‘==’ and ‘!=’, and ‘+’ and ‘-‘ operators. For the comparison operators we assume that our structs are equal if both counterparting components are equal, for addition and subtraction we will add or subtract components X and Y:

And that’s it. Our user-defined value type is ready to use. Of course we could override more operators and I guess is-bigger-than and is-lesser-that would be a good idea but it’s easy to do so if you want to extend the struct your good to go. Below you will find complete code for all above and code for unit tests.

Regards, Michał!

Coords
Tests

Inventor API: Custom add-in #3 – Working with the API, implementing the functionality

Hello there!
It’s time for the last part of our small tutorial on writing Inventor add-ins. Today we’ll write the actual implementation of the functionality described in previous post and explain some other small details. So, let’s get to work!

INVENTOR HANDLER

Our main functionality will be performed by a single class – InventorHandler (which will also be abstracted by IInventorHandler interface). It’s going to have only one public method AutoBreak() which will be responsible for applying the break to correct view. Let’s start with constructing it.

Private fields

It consist of three private fields: invInstance which stores reference to current instance of Inventor apllication, settings which stores reference to settings model and comparer which stores reference to IComparer implementation for sorting drawing views descending, area-wise.

This implementation is actually an internal class within our InventorHandler class. We won’t need that anywhere else.
Next, we have static list which contains orientation types which can work with our auto-break. This means that all views which are different orientation will not be take into consideration when executing auto break.

That list contain only perpendicular projections (back, left, right etc.) and the one called kArbitraryViewOrientation. This is the type of all views generated from a base view. This mean that although isometric views are not present this our collection the add-in will break that kind of view if it is created from an existing view.
The last thing is a predicate that is used for removing all views which are orientated differently than types allowed in the collection that we have just explained.

Constructor

The constructor for our InventorHandler class is very simple. It sets invInstance and settings to those given as arguments and instantiates new DrawingViewSizeComparerHelper class.

AutoBreak();

Now, let’s go through our only public method in the class:

It takes current active document in running Inventor application and sets a reference to in in a local variable drawing as a type DrawingDocument. Although property ActiveDocument of invInstance is of Document type (which is more general than DrawingDocument) it is safe to set is as DrawingDocument as our button to execute will be visible only in Drawing ribbon, therefore we’re sure that the active document IS DrawingDocument.
Next, we set another local variable which is of type DrawingView and assign result of getBiggest method executed with argument of drawing.ActiveSheet. This gets currently activated sheet in active document. If it’s null (meaning no drawing views are in the sheet) or it is too small to be broken the add-in will display a message and terminate execution of AutoBreak method. Otherwise, it continues.
Now, it checks if there already is a break applied to the view. If it is, again, it displays appropriate message and terminates.
Next step is to determine start and end points for the break. They are of type Point2d and they are set as local variables inside the method’s body. To give them appropriate values one of two methods is invoked: horizontalPoints or verticalPoints. These methods return boolean whether it is possible to break, and outs break points.
The last step is to apply the break:

It is done by executing Add method of BreakOperations collection in a view. It takes several arguments, as follows:

  • BreakOrientationTypeEnum – break orientation;
  • Point2D – start point;
  • Point2D – end point;
  • BreakStyleEnum – style of break, rectangular or structural;
  • integer – display level, in our case we pass default value of 5;
  • double – gap between left and right part of the view;
  • int – number of symbols, works only for rectangular view;
  • bool – propagate to parent view, defines if the break will be visible in parent view, in our case we pass default value true.

And that’s it. That’s the workflow. Now, as you probably noticed the method described above uses few private methods. To fully comprehend how the add-in works it is necessary to describe them as well.

DrawingView getBiggest(Sheet _sheet)

This method finds the biggest view in the given sheet. All views which are not orientated correctly (remember the list of ViewOrientationTypeEnum?) will be excluded from the selection.

bool isHorizontal(DrawingView _view)

Simply checks if a view is wider than higher and returns true if does.

bool canBeBroken(DrawingView _view, bool _isHorizontal)

This one checks if a view is sufficiently wide for horizontal break, or sufficiently high for vertical break. Minimum height/width is 5 cm plus gap. Remember that the API operates on centimetres expresses in variables of type double.

bool horizontalPoints/verticalPoints(DrawingView _view, int _percentage, out Point2d _start, out Point2d _end)

These two counterparting methods calculate start and end points based on given view and percentage of the view that needs to be removed. Methods return boolean whether a break can be applied and outs the points.

Converters

As some values from settings model are of simple types while methods exposed by the API require some arguments of different enum types there are two converters in the InventorHandler class: one is to convert boolean to BreakOrientationEnum

and the second one is to convert integer to BreakStyleEnum:

And that’s it if it comes to our InventorHandler class. However, to make the add-in actually work there are some changes needed in StandardAddInServer class.

CHANGES IN MAIN ADD-IN CLASS

First of all, we need an instance of InventorHandler. We’ll create a private field for that and initialise it in the constructor:

The last step is to modify action that is fired when the ‘Apply’ button is clicked:

And that’s it. The add-in is now functional. See the demo below:



FINAL REMARKS

There are two things I want to mention at this point. First, is about embedding the stdole assembly. When it’s added to the project and the project is built you will get a warning message:

Although, it does not affect the build you can get rid of these messages by setting Embed Interop Types property of stdole reference to false:

The other things is a word of explanation about NameValueMap interface. It used (amongst other uses) in the API to pass parameters in the events (as in our case events fired by clicking buttons). It works similarly to dictionaries, it stores pairs of name (which are strings) and values (which are of type object). I will not describe it in details (if you need that, simply go to its metadata in Visual Studio), but now you know the main thing – it is name/value pair to pass event parameters.

 

CONCLUSION

A vast portion of things can be manually done in Inventor can be automatised. However, the freedom in modelling that software gives you makes it really difficult to develop universal add-ins that will work always, no matter what you’re modelling. But all of translation, conversion, export things can be easily worked with. I know that there are some add-in that allow to generate models of sprockets, pulleys etc. and that works perfectly.
The hard thing when developing add-in is debugging. Possibilities here are limited because every time you want to debug you need to build your project and run the application, and you won’t get any error messages – either the application will crash, the add-in will be disabled or it won’t be executed.

To make things clear – I have worked with that software as a professional for more that 5 years and I am a big, big fan. I have experience with others systems, but this one seems to be most user-friendly, most of the features works as you would expect and has that professional-feel. But, it’s not a review, so I’ll stop here.
Thanks for your time, I hope that it is in any way useful for you. Good luck!
Michal

GitHub repo: https://github.com/mickaj/AutoBreaker-Inventor

Inventor API – Custom add-in Part #1
Inventor API – Custom add-in Part #2

Inventor API: Custom add-in #2 – Functionality and UI

Hello!
Writing our add-in for Inventor continues! Agenda for today’s post is simple: first I will write a word or two about what is the functionality of the add-in, then I will present the UI and what settings it provides, finally I will present the code.

FUNCTIONALITY

So, what will the add-in do? It allows user to place initial break to the biggest view in the drawing. It is rarely required in real world but the purpose of this demonstration is not to write something widely useful but to present how to write basic add-in for Inventor. Nevertheless, I wouldn’t be surprised if someone finds actual use for it. Feel free to do that 🙂
Inventor allows to set some parameters of the break. First and the most important is orientation. In our case that will be determined not by the user but automatically depending on proportions of the view. The rest will be allowed for customisation. As this is not an Inventor tutorial I am not going to describe in details how to manually add the break and what exactly can be customised. For such pieces of information you can easily find something on YouTube (for example this[1]).

UI PRESENTATION

As our add-in is very simple its UI is equally simple. Combo box for break style, slider for number of symbols (for structural style), text box gap which value will be converted to double and is expressed in centimetres, and slider ratio of how much of the view will be removed (minimum is 10%, maximum is 90%, however if the view is to small the break will not be applied). This small dialog is built in WPF and follows the MVVM pattern.

CODE

As this add-in will use WPF user interface I want it to follow the MVVM pattern, therefore we need model and view-model.

Model
So, let’s start with the model as this one is the simplest:

Style parameter is represented by an integer property backed by a field. The property setter allows only two values: 0 and 1 – that’s how two possible options are represented. Other possibility could be for instance a boolean, however integer is simpler to use with combo box. Similar situation with Symbols where setter allows only 1, 2, or 3 to be assigned; and with Range which can vary from 10 to 90. Gap is auto-property of type double. Class constructor sets initial values which are hard-coded. Natural extension would be to save those values somewhere so they are saved between sessions, however it’n not the point at the minute. The model class SettingsModel is additionally abstracted by ISettingsModel interface.

View-model
The view-model is slightly more complicated, but still quite simple.

First and foremost – it implements INotifyPropertyChanged interface. Fields and properties reflect the model, there are two things that require explanation. Range field/property backing field is of type double which is consistent with its counterpart in the model, while property is of type int which is consistent with slider’s value property. Gap field/property is of type string which will be bound to a textbox. The view-model also contains reference to model which is set via default constructor, constructor also assigns values from the model to respective fields in view-model. There is only one method which is used to save values from view-model to model; and there is only one command which invokes SaveToModel() method and closes settings dialog.

As mentioned SaveCommand is used to save values from view-model to model. It can be executed only when Gap value in view-model can be parsed to doubleExecute(object parameter) method casts parameter to type Window and invokes its Close() method to close the window. This require passing open instance of settings window to command parameter, which will be explained below.

View
Now, the view. There is one trick with WPF windows in Inventor add-in. If you try to add a WPF component to the project you will see that only user control is available, but the problem is that we need a window. A way to tackle that (source[2]) is to add what we can – a user control, and then change it to window. You need to do that in XAML code of the window and in the C# code behind. In XAML change root node to <Window>…</Window>, in C# code modify your class so it inherits from Window not from UserControl. And that’s it.

The only intresting thing in the XAML code above is how current instance of window is passed as command parameter:

The command parameter value is set to binding with RelativeSource set again to RelativeSource in FindAncestor mode with type of Window. This way  the current instance of window will be passed as command parameter which in turn is closed by the command.
Other than that, there are not exceptional things in the XAML, simply built UI with typical binding to view-model.
What you probably noticed, is that data-context is not set, and instance of view-model is not created in XAML, which requires the view-model to have parameter-less constructor, therefore some changes to add-inn StandardAddInServer main class are required.
Another thing worth mentioning is that closing (without saving settings to model) by clicking ‘Cancel’ button is achieved simply by an event assigned to that button, not by a command. This way to do that is much, much simpler than a command and because of the fact that it doesn’t interact with neither model nor view-model it doesn’t break the MVVM pattern.

Updates in StandardAddInServer
First thing that we need to do is to instantiate a model. The main class will be equipped in private field of type ISettingsModel […]

[…] which will be initialised in the class’ constructor.

The last thing we need to do is open the settings window when appropriate button is clicked. To do that we need a method that will be fired when the button is clicked.

The method above creates new settings window, sets it data-context to new instance of SettingsViewModel with current model as constructor’s parameter and finally shows the window as dialog.

And that’s it. Next (and the last) step will be to make ‘Apply!’ button to work. So, don’t forget to check my blog a little bit later.
Thanks, Michal!

GitHub repo: https://github.com/mickaj/AutoBreaker-Inventor

Sources:
[1] – https://www.youtube.com/watch?v=BzUAb9Qvu98
[2] – http://adndevblog.typepad.com/manufacturing/2015/11/wpf-window-inside-an-inventor-add-in.html

Inventor API – Custom add-in Part #1
Inventor API – Custom add-in Part #3

Inventor API: Custom add-in #1 – Introduction & modifying the ribbon

Hi!
Long time no see I might say… But there is a reason for that. As I mentioned in my previous post I turned my focus onto add-ins for Inventor and I have spent some time on that. Now, the plan is for short series of three post about writing add-in for Inventor. It will consist of three episodes: one – introduction and modifying the ribbon; two – description what the add-in we’re going to write in this series will do and its user interface in WPF; three – everything that resided under the hood and presentation how it works with Inventor.

TOOLS

In terms of tools there is nothing special needed. Obviously, Inventor needs to be installed and it’s SDK that comes along with the package. I do not own a licence for Inventor, but Autodesk allows for free 30-day trial to test their packages. The trial is for full package with no feature-limitations, however it is not allowed to use it for “commercial or for-profit purposes” [see here][1]. Writing these posts does not and will not violate either of those conditions, nonetheless if you are willing to write an add-in that will be used commercially you cannot do that with the trial. That having said we can move forward.
Once you have it installed it is necessary to install the SDK. It is an .MSI package you need to extract. It can be found in your Public Documents folder, then /Autodesk/Inventor2018/SDK. The package we’re interested in is developertools.msi. It will deliver some samples and – most important – project templates for Visual Studio. Unfortunately, the templates are for VS2015 so if you’re using VS2017 you will need to install older version as the templates will be installed only if Visual Studio is installed. If you still prefer to use VS2017 you can create project ins VS2015 and then open it newer IDE. I have not encountered any issues.

To sum things up, you will need:

  • Microsoft Visual Studio 2015 and optionally  Visual Studio 2017
  • Autodesk Inventor package which you can download with trial licence if you are not using it for commercial or profit purposes
  • Autodesk Inventor SDK developer tools installed that comes together with the software package

KNOWLEDGE BASE

Before I move on to the project I’d like to recommend two sources of knowledge about Inventor API. I already mentioned them in my previous post but to keep things organised I will do it again here.

  • Object Model Diagram – it is a PDF file that comes with the SDK developer tools and can be found in PublicDocuments/Autodesk/Inventor/SDK/DeveloperTools/Docs
  • this[2] repository on Git Hub. It contains thematically organised lessons on Inventor API with examples in C#

STARTING THE PROJECT

As mentioned before the templates are available for VS2015, so creating the project must be done in VS2015. All code written this series will be available on Git Hub. You will find a link at the end of this post.
Another thing that is important is to use correct version of .NET framework. I will be using Inventor2018 and it uses version 4.5. As I am aware most recent editions of Inventor uses 4.5 but if you want to be absolutely sure you can check that. To do that you need to go to your Inventor installation folder, then /Bin and open Inventor.exe.config file  in any text editor, then find <startup> tag section:

In the section above, the sku attribute defines version of the framework and in this case it is 4.5.
Having the project created you can save it, close and re-open in VS2017 if you prefer. Otherwise, you can continue in VS2015.
The last step would be to edit some values in AssemblyInfo.cs.

The project template is set up in a way that one the project is built all necessary files will be copied to appropriate location so the add-in will be visible in Inventor.
Having this done we almost can move on to modifying the application’s ribbon.

PROJECT REFERENCES

But before we start playing around with Inventor we need to add some references to the project. Right after project creation we only have references to autodesk.inventor.interop and System. We need bit more:

  • PresentationFramework – our UI will be build using WPF. You could use WinForms and I think that’s the preferred library, however I like WPF more. And that is the only reason for my decision.
  • System.Xaml – needed for WPF
  • stdole – that provides IPictureDisp interface that is going to be used for converting embedded icons to those usable with Inventor ribbons
  • System.Drawing – that provides Image abstract class and Icon class, needed for the same reason as above
  • System.Windows.Forms – that may seem suprising as I’ve already writtten that we’re going to use WPF. The reason behind the need of that reference is that AxHost base class to build our converter from Image objects to IPictureDisp usable with Inventor ribbons.

MODIFYING THE RIBBON

The application has several different ribbons. Which is used depends on what type of document is active and what environment is being used. To divide this series into episodes which are more or less equal length-wise I will just say now that the add-in will operate in drawing environment and will have two buttons: one to setup its preferences and the other one to run actions to be performed by the add-in.

First I will prepare two icon for our buttons. I downloaded some free icons from here. (I am absolutely talent-less if it comes to drawing). We need two size of each icon: 128×128@32bit and 16×16@32bit and they must be set as embedded resource. They will be stored in img folder in our project. So, to summarise: 4 files = 2 different icons x 2 different sizes.
Unfortunately, those icons cannot be used as they are. First, they must be converted to be of type IPictureDisp. To achieve that I’m going to use this[3] implementation (as proposed by Andrew Whitechapel at MSDN) of such converter:

As you can see our AxHostConverter class is an internal sub-class within our project main class StandardAddInServer. It won’t be used anywhere else so this approach is absolutely safe.
A method that creates instances of button definition as icons takes argument of type object, therefore they will be declared in StandardAddInServer class body as objects:

They will be in fact of type IPictureDisp in stdole namespace, but because of the fact that Inventor namespace also contains IPictureDisp type and avoid that confusion I will keep them as of type object. The process of retrieval from embedded resources and proper conversion will be performed by a private method getIcons() inside StandardAddInServer class:

So, that was the most confusing part. Now, it’s time start messing with the API. Adding our buttons to the application’s UI we need to start with defining some members in the class’ body:

The above fields will be initialised in another private method modifyRibbon(). The separate method is not needed however I like to have it separated just for a bit of clarity.
addInGuid string is copied value of Guid attribute from class signature. It will be later used to simplify a bit invocations of methods defining new buttons.

First two steps are easy, we just need to get some objects from currently running instance of Inventor, and that’s it.
Next step is to create command category for our add-in. It is done as in the code above, where arguments are as follow: strings for display name and internal name, and guid. Internal name is built as follows: “Autodesk:CmdCategory:our_custom_name“. This will add our category of commands that will be visible in UI customisation dialog:

Next, we need to access intended ribbon and one of its tabs. The ribbon we’re interested in is Drawing ribbon, the tab is Place Views.

As you can see they are accessible by their unique names and you must know them. They all can be found in mentioned earlier Git Hub repository here[4].

Next step – defining buttons:

It is achieved with use of ControlDefinitions and its AddButtonDefinition method. It takes several arguments (in respective order):

  • display name (string)
  • internal name (string) following scheme “Autodesk:command_category_name:button_name”
  • CommandTypesEnum – type of command, for UI elements it should be kQueryOnlyCmdType
  • add-in guid
  • description (string)
  • tool-tip (string)
  • standard icon (of type object, but it needs to be IPictureDisp)
  • large icon (of type object, but it needs to be IPictureDisp)
  • ButtonDisplayEnum – a way a button is displayed, in our case it is kAlwaysDisplayText

Once the button is defined we need to add action that will be performed when the button is clicked.

It the example above customAction method must return void and take one argument of NameValueMap which is set of name and value pair. It will be explained in one of later posts. For the time being, this method will only display a message box to demonstrate the buttons actually work.

The last step of defining a button is to add it to command category:

Now, we need to add panel to Place Views tab.

It is acheived using Add method in RibbonPanels collection in one of the ribbon tabs. It accepts arguments as follow:

  • display name (string)
  • internal name (string): “Autodesk:command_category_name:button_name
  • add-in guid

Now, we need to add our buttons to the created panel:

In the example above AddButton takes three arguments:

  • button definition
  • boolean – use large icon
  • boolean – display text

So, that’s it. The ribbon is modified. After changes described above it looks like that:

Nothing more to add today. Check the links below and stay tuned for the next part!
Cheers, Michal

GitHub repo: https://github.com/mickaj/AutoBreaker-Inventor

Sources:
[1] – https://www.autodesk.com/licensing/trial-license
[2] – https://github.com/ADN-DevTech/Inventor-Training-Material
[3] – https://blogs.msdn.microsoft.com/andreww/2007/07/30/converting-between-ipicturedisp-and-system-drawing-image/
[4] – https://github.com/ADN-DevTech/Inventor-Training-Material/blob/master/Module%2009%20-%20User%20Interface/RibbonNames.txt

Inventor API – Custom add-in Part #2
Inventor API – Custom add-in Part #3

Inventor API: EventTimingEnum

Hi there,
Some time ago I started writing an add-in for Autodesk Inventor. That software exposes an API that allow to develop add-ins in C#/.NET. In this post I am not going to write anything specific about the project; it will neither be an insight into API specifics. I just want to give quick explanation about controlling events with use of EventTimigEnum.

Some actions in Inventor can take a bit of a while – for instance placing big component into an assembly. Therefore, it is possible to decide when custom action is performed – either before or after an event is completed.

Let’s start this demo with writing a method that will be executed when a new component is placed into an assembly:

Just a brief explanation to the code above: of course only a method with matching signature can be assigned to an event, and it is necessary to set value of HandlingCodeEnum output parameter.
Now, to attach that method to an event that fires whenever a new component is inserted to assembly you need to access Inventor instance. In this example it will be done in add-in Activate method.

Once that is done we can start Inventor and see what’s the result:



As you have probably noticed our CustomAction was executed twice. Sometimes this behaviour is desired, sometimes it’s not. Now, let’s modify our method to perform action only after the event is completed. To do that we need to check value of EventTimingEnum parameter and perform action whenever its value is what we desire.

Now, the message box will be displayed only after the event is completed. EventTimingEnum can have one of three possible values: kAfterkBefore (which are self explanatory) and kAbort. The last value can be used in case we want to perform an action when an event is cancelled – for instance, when opening an assembly with lost reference user can decide to cancel opening.

It is also important to mention that not all events in Inventor are fired both kBefore and kAfter. Most of them are but you need to be aware that there are exceptions from that rule.

So that’s it if it comes to EventTimingEnum.
Unfortunately, there is not much about writing Inventor add-ins in .NET. What I recommend to check is first and foremost this GitHub repository:
https://github.com/ADN-DevTech/Inventor-Training-Material
It is complete course on Inventor API. There are presentations and code examples (in VB.NET and C#) for each chapter.
The other thing is class diagram delivered by Autodesk which comes with Inventor SDK installation. It can be found in Autodesk/Inventor/SDK/DeveloperTools/Docs in PublicDocuments on your C drive.
Regards, Michal

WPF: TreeView control

Hello there! It’s been a while since I finished GetNoticed contest and my last post here. I am done with SheetMetalArranger – at least for the minute. But that the contest is done doesn’t mean that I am done with programming. Not at all!

I started new project (maybe one time I will get back to SheetMetalArranger to improve it, but after ten weeks I need something fresh now). It doesn’t matter what the project is about at the minute (I will probably write a post or two about that), the important thing is that I’m continuing with WPF and the time has come to take a closer look at TreeView control.

Basics

TreeView control is used to display hierarchically organised structure. The best example is folder tree, for instance the one you have in Windows Explorer.

Here’s simplest example:

To build hard-coded tree you simply nest one <TreeViewItem> into another and build your structure. Notice that Header property is what is going to be displayed in your application. There are two other properties of TreeViewItem that should be mentioned here: IsExpanded and IsSelected which are pretty much self-explanatory but it is worth to mention them as they are fundamental for controlling behaviour of the control.

Binding

Binding a collection to TreeView can be easily achieved, it is no different as other controls. You simply bind a collection to ItemsSource property. But the tricky thing is that you need to reflect the hierarchy somehow. One way to do that could be binding a collection that contains objects of class TreeViewItem which is equipped in collection Items which contains child objects. Here’s the same example but with the difference that all data is stored in data model:

1) Lets start with the data model: our library node will consist of name, collection of books (stored as strings) and collection of sub-nodes.

2) Our actual data for the purpose of this example will be stored in static class with one static method GetData() that return instance of LibContainer

3) Our view model will consist of observalbe collection of TreeViewItems and in its constructor it will get data from the above static class. Inside the view model there is also one small private method that converts LibContainers to TreeViewItems

4) We set instance of view model and set it as data context. For example as below. Now, after that our tree view can be simplified just to only one line.

Load on-demand

The above example is nice and easy. It gets a bit more complicated when you want to load content of your tree view on-demand when content of your tree is huge and loading all data at once would be lengthy operation – I guess that’s common situation.

To achieve that we need to build custom class that will replace TreeViewItems in collection in our view model. That class must have: 1) collection of child items of the same class, 2) Parent, IsExpanded and IsSelected properties, 3) method to load children, 4) property that defines if the element can be expanded.

Here’s our example build this way:

What’s important in the code above is that Children collection must contain dummy element before actual elements are loaded. This is necessary because it would not be possible to expand the element, therefore it would not be possible to execute method that load further elements.

ViewModel class will now have only collection of TreeElement and will gather data from DataModel in its constructor.

Now, we need to define our TreeView control to display our custom items correctly. This is done by creating local style where we bind IsExpanded and IsSelected properties of TreeViewItem with counterparting properties of our custom TreeElement

And that’s it. This is how I use TreeView control. Possible extension to the above would be to create custom WPF control to handle custom types of tree elements and equip it with dependency property that exposes currently selected item. But that’s easy to do and isn’t in any way specific to TreeView.

So, thanks for today and good luck!

Sources:
WPF 4.5 Księga eksperta. Podręcznikprogramisty WPF 4.5! Adam Nathan (translated by Paweł Gonera, Ireneusz Jakóbik), published by HELION S.A 2005
https://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode