Visio VSTO Drag and Drop - drag-and-drop

I am trying to create a custom VSTO AddIn for Visio 2013 and 2015 where I have a list of items in an anchor view. I would like to allow the user to drag an item from the list and drop it on the Visio page. Once dropped I would like to use the x and y coordinates of the drop so that I can create specific shapes and connectors. I have not been able to find any articles or samples that shows how to get this done. The only reference I found was on how to achieve this for Word 2010 and I could not get the technique they used for Word to work for Visio.
Any assistance and guide would be greatly appreciated.

That's actually not that complicated. This (my) pretty old post explains how to drop shape from a memory stream:
http://unmanagedvisio.blogspot.co.at/2010/05/persisting-visio-shapes.html
If you want to drop from existing masters on a stencil (the code below assumes "Basic shapes", then it might be easier. You just need to handle "Item drag" in your form and then set the drag object to the desired master. DoDragDrop is a built-in function (the code below assumes winforms, for different framework you may need a different approach). Anyways, the basic idea is that "Master" visio object implements IDataObject interface, and that's enough to make drag-drop work.
Assuming your list view has two items, named "Triangle" and "Circle", if you drag "triangle" item, you should get "triangle" shape and for the "circle", the circle, respectively.
private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
var item = (ListViewItem) e.Item;
var app = Globals.ThisAddIn.Application;
var myStencil = app.Documents.OpenEx("BASIC_M.VSS",
(short)VisOpenSaveArgs.visOpenDocked | (short)VisOpenSaveArgs.visOpenRO);
var masterToDrag = myStencil.Masters[item.Text];
var data = new DataObject(masterToDrag);
DoDragDrop(data, DragDropEffects.Copy);
}

Related

Autodesk forge highlight child object

Recently i've been working on this repository https://github.com/xiaodongliang/forgeviewer_embed_in_powerbi_report to build a custom visual in Power BI to visualize the issues extracted from Bim track'S API.
The idea was visualizing them in associaton to the model's ROOMS.
In order to do that I worked with a NWC file, so i cuold export rooms as a geometry.
What i would like to do now is to highligt the rooms if a connected issue is selected from a table.
The problem is When i select an issue from a table, in the selection tree i can see highlighted the parent object name (ROOM) instead of the child (solid), and i think that is why i can't achieve my purpose (if not please correct me).
what i have
what i wold like to do
Does anyone know a way to do that?
If you would like to change your selection between (FIRST_OBJECT, LAST_OBJECT, LEAF_OBJECT) you can change viewer selection settings in order to test:
If you would like to achieve this programmatically :
Viewer.setSelectionMode();
could help you as well.
If I well understood, you want to highlight the child (which contain the mesh) instead of the parent.
The object highlight (isolate) is done in /forgePowerbiView/src/visual.ts with this code:
const dbIds = options.dataViews[0].table.rows.map(r =>
<number>r[0].valueOf());
console.log('dbIds: ' +dbIds)
this.forge_viewer.showAll();
this.forge_viewer.impl.setGhostingBrightness(true); //for isolate effect
this.forge_viewer.isolate(dbIds);
Take a look at this link Enumerating leaf nodes on Viewer. This will help you to get the dbIds you want to isolate.

CQ5/AEM: Creating sidekick components using 1 cq:component + multiple data nodes

I am working on a component that is essentially a building tool. I can't go into a lot of detail as to what it is, however the greatest parallel I can draw is that of a product list builder. The concept being that the author wants to create custom lists of products. These lists will live in a singular place and be referenced from many different pages within our content.
work flow:
create && build /content/myproductList
content/mySite/myPage/jcr:content/specialListView #property list points to /content/myproductList
Currently everything is pretty hunky dory and is working fine. The authors wanted the list building to be drag and drop, just like the rest of the site. So I created components to represent the list items and they can just open up a new builder, and drag/drop/reorder the list as much as they like and it will be refreshed within the 'specialListView'.
There is a huge flaw in my design and I want to see if I can overcome it. The flaw is etched in the way that I create the list item components. Essentially all of the items are structurally identical(in terms of markup), they just differ in content. So what I did was created a base component to control the markup and basic workflows (dialog, etc). Then I created a new component for each list item, these components have nothing but cq:template nodes that hold their information.
ex structure:
components/lists
| defaultItem
| defaultItem.jsp
| dialog.xml
| customeItem1
| .content.xml (resourceSuperType = components/lists/defaultItem)
| _cq_template.xml (has custom information)
| customeItem2
| .content.xml (resourceSuperType = components/lists/defaultItem)
| _cq_template.xml (has custom information)
...etc for 25+ items
By setting it up this way, we now have a workflow where the authors can drag and drop the components directly onto the page and not need to configure them or open dialogs and choose the correct dataset/etc. However, this seems extremely long winded and bulky. Scalability is an issue as well (what if they want to create 100 new items tomorrow -- sadly this is my reality).
What I'm proposing is to find a way to normalize this down so that I have a set of data (the list items) and 1 component to act as my structure.
something like:
/etc/data/lists/items
item 1
- nt:unstructured
- label=foo
- type=defaultItem
...etc
... etc, etc for all 25+ items
/apps/myapp/components/lists
defaultItem
| defaultItem.jsp
| dialog.xml
This is where I get stuck. If I have a structure like this, it makes it very difficult to have item1,item2,item3,...etc show up in the sidekick as drag and drop elements. I'm guessing I will need to get into the portion of JS that generates the sidekick items, but I'm not sure how to approach it from there (haven't messed with customizing the sidekick yet). Just looking for guidance if anyone has dealt with anything like this before.
[sidenote]
If you're curious why I'd like to move it to the second design, it's because eventually the authors would like a control panel that would allow them to create items on their own. It would be much easier and a lot more lightweight to have a system that alters a singular node and it's properties rather than one that has to manage creating/altering full component structures. It also decouples the 'item components' that the authors would make from the actual components that the developers create. This is important because the the component code we create is versioned/etc, whereas these faux components would go unchecked and we would need another way to manage them.
As you already described, creating a new component for each product will result in a big overhead. Beside you will create components, which are linked only to one resource, so not re-usable anymore.
First you need to see a difference between the content and components. In this case your defaultItem is the component and the products the content. In AEM the contentfinder is created to display, search, drag and drop your content into the page. The sidekick for components.
The solution will be the following:
Create a custom contentfinder tab which loads all your products;
Loading products can be done by creating a servlet which returns
all relevant products in a json format
Create a generic component (eg. defaultItem) which can display your
product into the page by setting a reference link to the product;
Configure the contentfindertab to create the defaultitem component
when dragging the product into the page
Take care about the CQ.wcm.ContentfinderTab.getResultsBoxConfig. At itemsDDNewParagraph
you can configure the new component type (defaultItem) and the
property to link the component to the product.
How to create a contentfinder tab:
http://helpx.adobe.com/experience-manager/kb/CustomCFTab.html
Note: when dropping a product from the contentfindertab into the page, use the ALT button

Getting individual elements from a Visio master group file using C#

I need to create a Visio document and add shapes from a .vss file. I am able to add simple shapes and add text to it without any issues. But I am having issues when I am trying to add a shape which is a collection of 4 rectangles grouped together (I believe it's called a master) and add texts to each shape.
I want to populate values (add texts) in each of these rectangle shapes in the group. Once I drop this master into the Visio page, it's appearing as a group. I am able to ungroup each rectangle with the Ungroup() method. But I don't know how to get each individual element from this group. Is there a way I can uniquely identify each element in this group? Or iterate through the group and find each element? Please see the code below, what I did so far.
Visio.Document doc = application.Documents.Add(#"\example.vst");
Visio.Page page = application.Documents[1].Pages[1];
Visio.Documents vdocs = application.Documents;
Visio.Document visioStencil = vdocs.OpenEx(#"\sample.vss", (short)Microsoft.Office.Interop.Visio.VisOpenSaveArgs.visOpenDocked);
Visio.Page visioPage = application.ActivePage;
Visio.Shapes visShapes = visioPage.Shapes;
//the following shape in the setensil is the group of 4 rectanle I was referring
Visio.Master visioConvMaster = visioStencil.Masters.get_ItemU(#"Conveyance");
Visio.Shape visioConvShape = visioPage.Drop(visioConvMaster, 4.25, 5.5);
//try to ungroup to get each
visioConvShape.Ungroup();
Any idea how I should proceed further? I am really new to Microsoft technologies. I am using Visual Studio 2012 professional & Visio 2010 Premium.
Thanks in advance.
Visio.Shape objects have a property "Shapes", which is a collection of child shapes. Don't ungroup; first, iterate through the Shapes collection (visioConvShape.Shapes[0], visioConvShape.Shapes[1], etc.) and then if you need to ungroup, do so after you have either at least performed whatever action you need to or identified them and/or given them reusable names.

The same C# code produces different output in Visio Professional and Premium

I have built a simple conversion Add In, but its behavior is unfortunately different with the different Visio Editions (Visio 2010 Professional and Visio 2010 Premium).
The Add In takes a Process-Diagram created with Shapes from Stencil_1.vss and creates a new slightly different Process-Diagram with Shapes from Stencil_2.vsd. It loops through a Visio page and for each shape founded creates a new shapes from new master shape (from Stencil_2.vsd) and drop it into the new page. Geometry, captions etc. are the same, only the shape-appearance is changed. Below is the source diagram:
When I run the code into Visio 2010 Professional the swimlane shapes are drawn correctly.
When I run the same code from Visio Premium the swimlane appearance and layout are mismatched:
Both times i drop the SAME Shape("Swimlane" from the same stencil) into the Page with the SAME Code fragment:
Visio.Master vm = swimlane_stencil.Masters.get_ItemU(#"Swimlane");
Visio.Shape TargetShape = targetPage.Drop(vm, shape_x, shape_y);
How could I ensure, that the code produces any time the same (correct) output? Must I disable any (premium)features in the swimlane-shapesheet?
The cross-functional flowchart shapes are backed by an addon so that shapes get correctly positioned within swimlanes and the page etc. Most shapes have an on drop event that calls out to the addon for their respective functionality.
By the looks of it the addon isn't being invoked correctly in your Visio Premium instance. For example, there's a function in the EventDrop cell:
=RUNADDONWARGS("CFF14","/cmd=20001")
..where CFF14 is the 2010 version of the cross-functional flowchart addon.
Bear in mind that 2010 also uses container shapes within the cross-functional flowchart solution. Are you using the correct 2010 'target' shapes?
There should be no difference in functionality, as far as the cross-functional flowchart is concerned, between Professional and Premium editions as far as I'm aware.
thank you for your time!
Bear in mind that 2010 also uses container shapes within the
cross-functional flowchart solution. Are you using the correct 2010
'target' shapes?
The ‘target’ shapes in both cases are the Swimlanes from the cross functional flowchart stencil.
I tested the same Add In-code on another "Professional"-Machine, it was successful, I mean the "Swimlane" shapes are positioned correct and without separators and Title-section.
I also uninstall and install again the Premium instance and nothing is changed, the same code produces the same diagram drawn above. Swimlanes PinX are changed and separators and title-section are added.
I noticed, that in the “wrong diagrams” only the first dropped
Swimlane shape is correct
The following(later dropped) Swimlanes are wrong positioned and separators and title-bar are added. They have:
User.msvShapeCategories="CFF Container;DoNotContain", the right Swimlane-shapes have: User.msvShapeCategories="Swimlane;DoNotContain"
Also I noticed, that the wrong Swimlanes are derived
from xfunc_m.vss ( User.visMasterStencil = "xfunc_m.vss")
I remove the value “xfunc_m.vss” from the User.visMasterStencil Cell
and update the stencil
Now it works fine, I hope this explanation is useful for others and somebody could explain this behavior better than me :)

Drag n' Drop spark List Itemrenders betwen components

I'm trying to do some drag and drop between 2 spark List located in different components.
Because my first attempt didn't work, I decide to Google it and read some more about DragAndDrop ... tried all the examples I could find but nothing seams to work for me.
So let's go to the point.
Component A has List1
Component B has List2
Component A - List 1 has dragEnabled="true" and mouseDown="initiateDrag(event)"
private function initiateDrag(e:MouseEvent):void{
var dragInitiator:IUIComponent = e.target as IUIComponent;
var de:DragSource = new DragSource;
de.addData(dragInitiator, 'artist');
DragManager.doDrag(dragInitiator, de, e);
}
By what I read, usind the mouseDown I'm starting a the drag event creating what kind of data I'm going to drag ... this case 'artist'
Component B - List 2 has dropEnabled="true", dragEnter="dragEnterHandler(event)" and dragDrop="dragDropHandler(event)"
private function dragEnterHandler(e:DragEvent):void{
if(e.dragSource.hasFormat('artist')){
DragManager.acceptDragDrop(List(e.currentTarget));
}
}
Now, what I'm expecting was, when I drag the itemRender from Component A List 1 over Component B List 2 is to call the function dragEnterHandler(event), and it does ... but I was also expecting that the DragManager.acceptDragDrop(List(e.currentTarget)) whould change indicator from the "red cross" to the "green plus" and that's not happening ... and because of that, the dragged itemRender (proxi) moves back to its original list in this case it moves back to Component A List 1
I already spent hours and hours debugging and testing other approaches and none seams to work for me.
Is there anyone here familiarize with drag and drop between components that may help me?
Well guys, looks like after 2 days and 4h later I got the solution :)
I was looking to this in a complete wrong way.
When using Drag and Drop with List based components, the 'format' is always 'itemsByIndex' and I was trying to be accepted with 'artist' 'format'.
Problem:
You have more than one List accepting data with a drag-and-drop method.
Different lists has to accept different types of data.
Solution:
Wrap the <s:List/> in <s:Group/> and manually call the dragEnter event and with it you call a function that can accept or reject the dragged data by checking it's 'format'.
Accepting the drag source, the dragDrop event is dispatched and with that you can call a function to do whatever you want in your app ... for example, add the dragged data to the list.
NOTE:
Remember if tou set the dragEnter and dragDrop directly on the component, you will ne be able to check the dragged data 'format' given all list controls uses the 'format' 'itemsByIndex'
Demo:
<fx:Script>
<![CDATA[
private function dragEnterHandler(e:DragEvent):void{
if(e.dragSource.hasFormat('artist')){
var dropTarget:Group = Group(e.currentTarget);
DragManager.acceptDragDrop(dropTarget);
}
}
private function dragDropHandler(e:DragEvent):void{
// Check is the data alreay exists in the list;
// Adds the data to the list dataGroup;
// Do whatever you want ...
}
]]>
</fx:Script>
<s:Group id="myGroup"
dragDrop="dragDropHandler(event)"
dragEnter="dragEnterHandler(event)">
<s:List id="myList"
dataProvider="{myDataProvider}"/>
</s:Group>
Hope this helps other people with the same problem! :)