BreadCrumb control made simple

breadCrumb

“Hard by a great forest dwelt a poor wood-cutter with his wife and his two children… Gretel took the bread under her apron, as Hansel had the pebbles in his pocket… Hansel, however, little by little, threw all the crumbs on the path…”

OK, ok, this was another story, however, the breadcrumb control is a great invention. It’s basically a horizontal way to navigate structures, like a folder structure, and generate a path through that structure. This is perfect for navigating through the Vault folder tree and select the path where to save our files with Data Standard.

breadCrumb

Now unfortunately, there is no Microsoft default control we could just use in our Data Standard dialogs. Fortunately, there are several vendors that offer great looking breadcrumb controls such as Telerik, Actipro, and others. Unfortunately, if you like to purchase one of these, read well the user license agreement, as Vault and Data Standard are “development platforms” themselves, so finally the Vault customer would have to purchase the license.

I took another approach. I thought why not having a list of cascading comboboxes. The list should be flexible and somewhat intelligent, in the sense that when I choose to change the path, the superfluous combos should be removed and replaced with the new selected path.

I know, this is not a 100% breadcrumb control and all of you skilled developers will laugh at me, but this is a cheap, simple, functional solution, so give me a break!

I took advantage of the StackPanel, which is a simple control that just stacks child controls either horizontal or vertical. In my case, I want the comboboxes stacked horizontally. The next step is to create and add dynamic comboboxes as child controls to the StackPanel, and fill them with the according list of Vault folders. As the user selects one folder from the first combo, a second combo will be added with the according child folders. As the user selects a folder from the second combo, a third will be added, and so on, until no more child folders exists. In case the user changes one of the previous folders, the child combos will be removed and the game starts over. Here is the code in the XAML.

...
<StackPanel Grid.Column="1" Grid.Row="4" Name="BreadCrumb" Orientation="Horizontal"/>
<!--ComboBox Grid.Column="1" Grid.Row="4" SelectedValue="{Binding Prop[Folder].Value}" SelectedIndex="0" Style="{StaticResource FolderStyle}" /-->
...

As you can see I just commented the combo box for the folder selection in the standard dialog and instead I’ve added the StackPanel mentioned above. As you can see the StackPanel is empty by default, but has a name. The rest is done in PowerShell.

In the InitializeWindow (Default.PS1), we take the starting folder and add them to the function AddCombo. The rest is done in a separate PS1 called breadcrumb.ps1.

$mappedRootPath = $Prop["_VaultVirtualPath"].Value + $Prop["_WorkspacePath"].Value
$mappedRootPath = $mappedRootPath -replace "\\", "/" -replace "//", "/"
$rootFolder = $vault.DocumentService.GetFolderByPath($mappedRootPath)
$root = New-Object PSObject <em>-Property</em> @{ Name = $rootFolder.Name; ID=$rootFolder.Id }
AddCombo -data $root

The function AddCombo gets the child Folders for the selected folder, adds a first combobox to our StackPanel, fills the combobox with the child folders and registers the SelectionChanged event. You will notice that the child folders are not just a list of text, but are little objects. The reason is that we want to store both, the name of the folder and the ID, so when we have to look for the children, we have the ID of the parent already at our hand.

function AddCombo($data)
{
 $children = GetChildFolders -folder $data
 if($children -eq $null) { return }
 $breadCrumb = $dsWindow.FindName("BreadCrumb")
 $cmb = New-Object System.Windows.Controls.ComboBox
 $cmb.Name = "cmbBreadCrumb_" + $breadCrumb.Children.Count.ToString()
 $cmb.DisplayMemberPath = "Name"
 $cmb.ItemsSource = @($children)
 $cmb.add_SelectionChanged({
 param($sender,$e)
 OnSelectionChanged -sender $sender
 })
 $breadCrumb.Children.Add($cmb)
}

The OnSelectionChanged is fired every time the user selects another value from the combo. In such case, we just take the selected folder and call the AddCombo with such folder. Before we do so, we remove all child combos, if they exist. That way, in case the user decided to go another path, the superfluous child combos get removed and the game can start over again.

function OnSelectionChanged($sender)
{
  $breadCrumb = $dsWindow.FindName("BreadCrumb")
  $position = [int]::Parse($sender.Name.Split('_')[1]);
  $children = $breadCrumb.Children.Count - 1
  while($children -gt $position )
  {
    $breadCrumb.Children.Remove($breadCrumb.Children[$children])
    $children--
  }
  $path = GetFullPathFromBreadCrumb -breadCrumb $breadCrumb
  $Prop["Folder"].Value = $path
  AddCombo -data $sender.SelectedItem
}

That’s it! there are two more little functions such as the GetFullPathFromBreadCrumb and GetChildFolders which contain few lines of code, but the real important functions are the two above. As you can see in the OnSelectionChanged the property Folder gets set whenever the user selects a new path.

If you like to try this code, you can download the complete sample from here https://github.com/coolOrange-Public/breadCrumb/archive/master.zip.

 

Posted in Data Standard, PowerShell, Vault API | 2 Comments

And the winner is…

2015-01-21_09-17-17

Wow. We got a lot of valuable feedback. Thank you for that! We will keep the survey open in case some more people like to provide input. However, the trend is already clear. You definitely want technical stuff that can be packaged into your projects. The topics preference is somewhat distributed between Data Standard (1st), Vault API (2nd), powerJobs, powerGate, Vault migrations and other topics. The preferred day for reading posts is Monday (43%) and Friday (31%), and the frequency of one post per week (70%) is good.

So we will keep going with posts on Friday, which works well for both the Friday and Monday readers, and we will continue posting on Data Standard and other Vault related topics as well as our products. Based on your feedback, we will see to provide more tips on how the Vault behavior can be improved or extended and how technologies work better together. If you like to suggest other topics of interest, feel free to either fill out the survey https://de.surveymonkey.com/s/Blog2015, or send us an email to blog@coolorange.com. We will see to take your suggestion into account and post about it.

Thank you very much for the feedback so far and for the kind words! All bloggers knows the effort for driving a blog and such comments are fuel for our engines!

Posted in Uncategorized | Leave a comment

Let’s talk about…

blog2015

Happy new year!!! We are back and like to share with you some more interesting topics. In order to provide the right content for you, we would like to better understand which topics you are interested in. Are you more technical or commercial oriented, a reseller or customer, do you like to know more about API, Data Standard, custom jobs, ERP integration, …

We prepared a short survey that I kindly ask you to fill out. It takes less then 5 minutes. All the information is anonymous. Based on the results we will create content that will help you in your business. Please take the time and follow this link https://de.surveymonkey.com/s/Blog2015

Looking forward to your feedback!

Posted in Uncategorized | Leave a comment

Happy holidays!

2014 is slowly coming to an end, and we wanted to take the chance and say THANK YOU to all our loyal blog-readers.

The year 2014 was an extraordinary one. There have never been more blogposts, blog-readers, and comments. In the next year, we will bring you more helpful tips and tools for Data Standard, PowerShell, powerJobs, powerGate, Inventor apps, and there are also more new interesing topics to come.

For those of you, who are not solely interested in the deep-tech stuff, but also in more high level info, we launched a newsfeed on our website, where we post all sorts of interesting information about new products, completed projects, customer case studies, promotions and so on.

Click on our christmas tree and check it out! Merry Christmas!

 

christmastree

Posted in Uncategorized | Leave a comment

Summary from the AU Data Standard session

AU2014

Last week, I had the pleasure to meet you at the Autodesk University in Las Vegas. Thanks for the good talk and great feedback. The session around Data Standard introduction was well attended and the ratings were great – beyond 9.3 – THANK YOU for that!

In the short time I tried to give you an overview on what Data Standard is and gave you several examples on how Data Standard can be customised in order to achieve interesting Vault improvements. Although the material is available on the AU page, I’d like to make the presentation and the customisations available here. Some of the topics covered during the session have already been posted on this blog. The other topics will be posted in the next weeks with additional information on how they work.

So, have fun with the Data Standard introduction presentation and the DataStandard samples. I hope with these topics, we are able to engage your imagination of what could be done with Vault. If you have further ideas we should blog on, just leave a comment.

Posted in Data Standard, PowerShell, Vault API | 2 Comments

Password protected PDF

A customer asked us if it is possible to create a password protected PDF with powerJobs. The answer is YES, it is!

Here is the PowerShell code for protecting a PDF file with a password:

[System.Reflection.Assembly]::LoadFrom("itextsharp.dll")

function PSUsing {
 param (
 [System.IDisposable] $inputObject = $(throw "The parameter -inputObject is required."),
 [ScriptBlock] $scriptBlock = $(throw "The parameter -scriptBlock is required.")
 )
 
 Try {
 &$scriptBlock
 }
 Finally {
 if ($inputObject.psbase -eq $null) {
 $inputObject.Dispose()
 } else {
 $inputObject.psbase.Dispose()
 }
 }
}

$file = New-Object System.IO.FileInfo "C:\Temp\test.pdf"
$fileWithPassword = New-Object System.IO.FileInfo "C:\Temp\test_password.pdf"
$password = "secret"
PSUsing ( $fileStreamIn = $file.OpenRead() ) { 
 PSUsing ( $fileStreamOut = New-Object System.IO.FileStream($fileWithPassword.FullName,[System.IO.FileMode]::Create,[System.IO.FileAccess]::Write,[System.IO.FileShare]::None) ) { 
 PSUsing ( $reader = New-Object iTextSharp.text.pdf.PdfReader $fileStreamIn ) {
 [iTextSharp.text.pdf.PdfEncryptor]::Encrypt($reader, $fileStreamOut, $true, $password, $password, [iTextSharp.text.pdf.PdfWriter]::ALLOW_PRINTING)
 }
 }
}

You can see, we are using iTextSharp for doing this. Please download the library from here and extract the content of itextsharp-dll-core.zip to the folder where you will place your powerShell script later.

The file that you specify for $file variable will be stored with password-protection to the file $fileWithPassword.

Just run the script and open the new file with any PDF viewer and you should get this:

04-12-2014 10-03-34

Bam! That’s all. Have fun!

Posted in powerJobs, PowerShell, Uncategorized, Vault API | Leave a comment

Select Vault items from within CAD

itemSelection

How would it be to select an item from Vault directly within Inventor? Yes, I’m in an Inventor model or drawing and via the Data Standard dialog I can pick an existing item from within Vault. Once again, we do this with Data Standard. So, we add an additional tab to the Inventor or AutoCAD Data Standard dialog and either at save or later, the user can place a search onto the Vault items and then select one of the resulting items. The item number will be stored into the Part Number within the Inventor file.

SelectItem

Once the file is checked in, as the part number matches with an existing item, at the assign-item operation, the association will be automatically done.

The customization for this sample involves 2 files. The Inventor.XAML and a new PS1 file. The XAML file has been enhanced with an additional tab and the according search TextBox and a DataGrid for the results. Here the XAML code for the Item tab:

<TabItem Header="Items" HorizontalAlignment="Left" Height="20" VerticalAlignment="Top" Width="55">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="auto"/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="auto"/>
      </Grid.ColumnDefinitions>
      <TextBox x:Name="SearchText" Grid.Column="0"/>
      <Button Grid.Column="1" Content="Search" Margin="5,0,0,0" Command="{Binding PsCmd[SearchItem]}" CommandParameter="{Binding Text, ElementName=SearchText}"/>
    </Grid>
    <DataGrid Grid.Row="1" x:Name="ItemsFound" AutoGenerateColumns="True" IsReadOnly="True" ColumnWidth="Auto" HorizontalGridLinesBrush="WhiteSmoke" VerticalGridLinesBrush="WhiteSmoke">
      <DataGrid.ContextMenu>
        <ContextMenu>
          <MenuItem Command="{Binding PsCmd[SelectItem]}" Header="Select item" CommandParameter="{Binding SelectedIndex, ElementName=ItemsFound}"/>
        </ContextMenu>
      </DataGrid.ContextMenu>
    </DataGrid>
  </Grid>
</TabItem>

As you can see the Button for the search is bound to a PowerShell function called SelectItem. The entered search text is passed as a CommandParameter to the Button. The DataGrid is somewhat simple as we use the AutoGenerateColumns in order to get the appropriate columns. You’ll notice that we defined a little context menu for the DataGrid. So the user will be able to fire the “Select Item” command.

Let’s have a look to the PowerShell file:

Add-Type @"
public class itemData
{
  public string Item {get;set;}
  public string Revision {get;set;}
  public string Title {get;set;}
}
"@

function SearchItem()
{
  if($mvparam -eq '') { return }
  $srchconds = New-Object autodesk.Connectivity.WebServices.SrchCond[] 1
  $srchconds[0] = New-Object autodesk.Connectivity.WebServices.SrchCond
  $srchconds[0].PropDefId = 0
  $srchconds[0].SrchOper = 1
  $srchconds[0].SrchTxt = $mvparam
  $srchconds[0].PropTyp = "AllProperties"
  $srchconds[0].SrchRule = "Must"
  $bookmark = ''
  $status = New-Object autodesk.Connectivity.WebServices.SrchStatus
  $items = $vault.ItemService.FindItemRevisionsBySearchConditions($srchconds, $null, $true, [ref]$bookmark, [ref]$status)
  $results = @()
  foreach($item in $items)
  {
    $row = New-Object itemData
    $row.Item = $item.ItemNum
    $row.Revision = $item.RevNum
    $row.Title = $item.Title
    $results += $row
  }
  $dsWindow.FindName("ItemsFound").ItemsSource = $results
}

function SelectItem
{
  $selectedItem = $dsWindow.FindName("ItemsFound").SelectedItem
  $Prop["Part Number"].Value = $selectedItem.Item
  $dsWindow.FindName("DataTab").IsSelected = $true
}

Similar to our last post about the item tab, we create a small C# class with few properties. The function SearchItems checks whether the arguments passed to the Button via the CommandParamenter are empty. In that case the function just returns and does nothing. Otherwise a generic search on the item master will be performed. How did I came across the settings for the search condition? I just started the vapiTrace and run a generic search in Vault. Then I read the function name and arguments from the vapiTrace.

The result of the search is then transformed into a list of our custom class and set as ItemsSource to the DataGrid.

As for our XAML, the DataGrid has a little context menu item with the “Select item” command. The bound function is the SelectItem, which sets the property Part Number to the selected number and then sets the first tab as active.

That’s it! Of course we can enhance this sample by showing more information for the items, or we can additionally filter the result and show just some data. We can also think or letting the user create new items right from within Inventor or AutoCAD. Then of course the XAML and code would be a bit longer. But overall, I think this sample shows a bit of XML and PowerShell technique, and with a few lines of code the result is quite impressive!

If you like to try this out, just download the ZIP package.

Posted in Data Standard, PowerShell, Vault API | 1 Comment