Update: Multiple Input Form With Dynamo

Written by:

  • I hesitated between updating the previous post directly or posting a new post. I finally decided to make it a new post so that it’s not too long to read. I will only develop on new stuff here.

I have updated the UI.MultipleInputForm so it could handle more input types:

newnode
UI.MultipleInuptForm, Data-Shapes package

 

Here is the Input type codification:

winforms
Input type codification

 

1. Revit Selection Inputs:

The Revit element, face, and edge selection inputs are pretty straight forward. These type of inputs generate a button that allows interaction with the Revit model. The selections are then output as lists. Here is an example with the “se” (select Revit element) input type:

select-element
Revit element/face/edge selection inputs

2. ComboBox Inputs:

String and Number lists:

The combo box is the only input that needs special treatment, because there is no codification.  In order to create a drop-down list input in the form, you just need to feed your drop down list items as a one level nested list within the InputTypes list. The list structure is very important here.  The List.Create Node is perfect for creating the right input:

combonew
Drop-down list input creation

 

You can- of course- add as many drop down lists as you want:

multi-dropdown
A form with multiple drop-down lists

 

 

Revit Element lists:

In case you use Revit elements as items for your drop down list, the node will display the name of the elements, and return the Revit element as an output:

revitelement-list
Using Revit elements as drop-down list items

 

3. Form features:

I have also added a couple of features to the form. I followed Brendan Cassidy’s example and deleted the maximise/minimise and resize options. I also set the form so that it would always be in the forefront, this way it will never be hidden which could prevent Dynamo and Revit from working.

This node should make it a little easier for those allergic to Dynamo to benefit from its power!

Here’s the code to the node:


#Copyright (c) mostafa el ayoubi , 2016
#Data-Shapes http://www.data-shapes.net , elayoubi.mostafa@gmail.com
import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
from System.Drawing import Point
from System.Windows.Forms import Application, Button, Form, Label, TextBox, CheckBox, FolderBrowserDialog, OpenFileDialog, DialogResult, ComboBox, FormBorderStyle
from System.Collections.Generic import *
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import Selection
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
class MultiTextBoxForm(Form):
def __init__(self):
self.Text = 'Data-Shapes | Multi Input UI'
self.output = []
self.values = []
def setclose(self, sender, event):
cbindexread = 0
for f in self.output:
if f.GetType() == TextBox:
self.values.append(f.Text)
if f.GetType() == CheckBox:
self.values.append(f.Checked)
if f.GetType() == Button:
if f.Tag == None :
self.values.append(f.Text)
else:
self.values.append(f.Tag)
if f.GetType() == ComboBox:
self.values.append(globals() ['dict%d'%(cbindexread)][f.Text])
cbindexread += 1
self.Close()
def reset(self, sender, event):
pass
def openfile(self, sender, event):
ofd = OpenFileDialog()
dr = ofd.ShowDialog()
if dr == DialogResult.OK:
sender.Text = ofd.FileName
def opendirectory(self, sender, event):
fbd = FolderBrowserDialog()
dr = fbd.ShowDialog()
if dr == DialogResult.OK:
sender.Text = fbd.SelectedPath
def pickobjects(self, sender, event):
sel = uidoc.Selection.PickObjects(Selection.ObjectType.Element,'')
selelem = [doc.GetElement(s.ElementId) for s in sel]
sender.Tag = (selelem)
def pickfaces(self, sender, event):
selface = uidoc.Selection.PickObjects(Selection.ObjectType.Face,'')
faces = [uidoc.Document.GetElement(s).GetGeometryObjectFromReference(s).ToProtoType(True) for s in selface]
sender.Tag = [i for f in faces for i in f]
def pickedges(self, sender, event):
seledge = uidoc.Selection.PickObjects(Selection.ObjectType.Edge,'')
edges = [uidoc.Document.GetElement(s).GetGeometryObjectFromReference(s).AsCurve().ToProtoType(True) for s in seledge]
sender.Tag = edges
def topmost(self):
self.TopMost = True
form = MultiTextBoxForm()
form.topmost()
xlabel = 25
xinput = 125
y = 10
fields = []
error = 0
cbindex = 0
#Input form
if isinstance(IN[0],list):
inputnames = IN[0]
else:
inputnames = [IN[0]]
if isinstance(IN[1],list):
inputtypes = IN[1]
else:
inputtypes = [IN[1]]
for i,j in zip(inputnames,inputtypes):
label = Label()
label.Location = Point(xlabel,y+4)
label.Height = 20
label.Width = 80
label.Text = str(i)
form.Controls.Add(label)
if isinstance(j,list):
cb = ComboBox()
cb.Location = Point(xinput,y)
cb.Width = 150
globals()['dict%d'%(cbindex)] = {}
try :
for k in j:
globals()['dict%d'%(cbindex)][k.Name] = k
cb.Items.Add(k.Name)
except :
for k in j:
try:
globals()['dict%d'%(cbindex)][str(k)] = k
except:
globals()['dict%d'%(cbindex)][k.encode('utf-8').decode('utf-8')] = k
cb.Items.Add(k)
form.Controls.Add(cb)
form.output.append(cb)
cbindex += 1
elif j == 's':
tb = TextBox()
tb.Text = 'Default'
tb.Width = 150
tb.Location = Point(xinput,y)
form.Controls.Add(tb)
form.Controls.Add(label)
form.output.append(tb)
elif j == 'bool':
yn = CheckBox()
yn.Location = Point(xinput,y)
yn.Text = 'Yes/No'
form.Controls.Add(yn)
form.output.append(yn)
elif j == 'fp':
fp = Button()
fp.Width = 150
fp.Text = 'FilePath'
fp.Location = Point(xinput,y)
form.Controls.Add(fp)
fp.Click += form.openfile
form.output.append(fp)
elif j == 'dp':
dp = Button()
dp.Width = 150
dp.Text = 'DirectoryPath'
dp.Location = Point(xinput,y)
form.Controls.Add(dp)
dp.Click += form.opendirectory
form.output.append(dp)
elif j == 'se':
se = Button()
se.Width = 150
se.Text = 'Select model element(s)'
se.Location = Point(xinput,y)
form.Controls.Add(se)
se.Click += form.pickobjects
form.output.append(se)
elif j == 'sf':
sf = Button()
sf.Width = 150
sf.Text = 'Select face(s)'
sf.Location = Point(xinput,y)
form.Controls.Add(sf)
sf.Click += form.pickfaces
form.output.append(sf)
elif j == 'sed':
sed = Button()
sed.Width = 150
sed.Text = 'Select Edge(s)'
sed.Location = Point(xinput,y)
form.Controls.Add(sed)
sed.Click += form.pickedges
form.output.append(sed)
else :
error = 'One or more input types are invalid, visit http://www.data-shapes.net for more informations'
y+= 30
button = Button()
button.Text = 'Set values'
button.Width = 150
button.Location = Point (100,y+30)
button.Click += form.setclose
form.Controls.Add(button)
form.MaximizeBox = False
form.MinimizeBox = False
form.FormBorderStyle = FormBorderStyle.FixedSingle
form.Height = y + 120
if error == 0 and IN[2] == True:
Application.Run(form)
result = form.values
OUT = result,True
elif IN[2] == False:
result = "Set toggle to true!"
OUT = result,False

30 responses to “Update: Multiple Input Form With Dynamo”

  1. Marlo Melching Avatar
    Marlo Melching

    This is a great resource!

    I noticed a couple of things:
    – The latest version (13-11-2016) doesn’t allow multi inputs. the older versions do.
    – The dropdown list doesn’t seem to work at the moment either.

    This is the only source for a UI i’ve come across on the web, very useful

    Like

    1. data|shapes Avatar
      data|shapes

      Hi Marlo, Thank you for the feedback. I just ran a test and it turns out the issue comes from the way the python node is wrapped in the custom node. Thanks for pointing this one out!
      Please update the package to the vesrion 2016.11.15 ans let me know if it’s working fine for you.

      Like

      1. Marlo Melching Avatar
        Marlo Melching

        I’ve tried it, and it works as a charm now.
        Also i’ve been looking at the code and i noticed it’s not possible to fill in a default value. Will this be possible in the future?

        Recently i’ve been working on several Revit Add-Ins, and if you’d like i can test your new versions and maybe also add some idea’s to add new functionality.

        Cheers

        Liked by 1 person

    2. data|shapes Avatar
      data|shapes

      allowing a default input value would indeed be a good idea. I was trying to keep the inputs to the minimum, in order to keep is as simple as possible. I have been thinking about making another node with more inputs, like default values and styling options. I will definitely keep you posted when it’s ready !

      Like

  2. Wojciech Klepacki Avatar
    Wojciech Klepacki

    Amazing. That’s simply amazing. Thanks for this handy tool. I will give it a try.

    Liked by 1 person

  3. Multi User Input Form with Dynamo – data|shapes Avatar
    Multi User Input Form with Dynamo – data|shapes

    […] there has been an update with more input types! See more here . […]

    Like

  4. Bird Avatar
    Bird

    hi Grea node. i have update dynamo to 1.2.1

    UnicodeDecodeError: (‘unknown’, u’\xb0′, 0, 1, ”)

    Like

    1. data|shapes Avatar
      data|shapes

      Hi Brid,
      I’m glad you find it useful. Is that an error you get whith version 1.2.1 ?
      I just tried all input types with that version and it seems to work.
      Could you please post more information about the issue you meet on the github repository :
      https://github.com/MostafaElAyoubi/Data-shapes/issues .
      Thanks!

      Like

  5. Scott Avatar
    Scott

    Terrifically useful node – thanks so much for creating and sharing! If I had the ability I would love to modify to allow multiple selection listboxes for input Alas my coding skills are currently limited to the now archaic Pascal and FORTRAN.

    Liked by 1 person

    1. data|shapes Avatar
      data|shapes

      Thanks for the feedback Scott! I’ll try and have that in the next release of the package along with some other new features. Stay tuned!

      Like

  6. bikashseas Avatar
    bikashseas

    Hi want to use this.But I am facing
    warning:
    IronPythonEvaluator.EvaluateIronPythonScript
    operation failed.
    Traceback(most recent call last):
    File””,line 101,in
    IndexError:index out of range: 1

    Like

    1. data|shapes Avatar
      data|shapes

      Hi Bikashseas ,
      Could you please post a screenshot of your inputs in the github repository ( https://github.com/MostafaElAyoubi/Data-shapes/issues ) or dynamo forum so I can look into it ?

      Liked by 1 person

      1. bikashseas Avatar
        bikashseas

        Hi solved that problem,but now I am facing another.Droop down menu is not working.
        I posted it in Dynamo forum.Please see it.

        Like

  7. Duy Vu Avatar
    Duy Vu

    Hi ,
    I tried to create multi UI , like this : https://drive.google.com/file/d/0B9fh1NlhI20wNUpXeldwNEtxWTg/view

    Sometimes it doesn’t follow that order.

    Like

    1. data|shapes Avatar
      data|shapes

      Interesting use 🙂
      I added an output to the node in order to allow that :

      You must update the package to 2016.12.08

      Like

      1. Duy Vu Avatar
        Duy Vu

        Awesome! Sincerely thanks 🙂

        Liked by 1 person

  8. Batch add shared parameters from .txt file with UI.MultipleInputForm ++ – data|shapes Avatar
    Batch add shared parameters from .txt file with UI.MultipleInputForm ++ – data|shapes

    […] This workflow is a good exemple of how you can set the InputTypes list. All the previous input type codifications still work of course. You can see it here. […]

    Like

  9. Duy Vu Avatar
    Duy Vu

    Hi,
    Mutilple elements selection sometimes made revit stop working. Could you add an element selection ? I appreciate it 🙂

    By the way, this is my script that was built form your UI and Archi-lab. I’ve been trying to create and add filter by dynamo with UI input. I’m still perfecting it.

    https://drive.google.com/file/d/0B5JiAYYvbI8eUUw5TXE0dHV3N00/view?usp=sharing

    Liked by 1 person

    1. data|shapes Avatar
      data|shapes

      Hi Duy Vu ,
      I tried your script on Revit 2017 and Dynamo 1.2.1 and it all seems to work fine. Don’t forget to press finish when you’re done selecting the elements :

      What do you mean by “could you add an element selection” ?

      Like

      1. Duy Vu Avatar
        Duy Vu

        Yep, it is working fine. In my case, I just want to select an element, pressing finish is a waste of time, and when I forget press finish, it make revit stop working.
        Sorry my english is not good. I mean this “an element selection” :

        https://drive.google.com/file/d/0B5JiAYYvbI8eelFwVkRFLXNibTA/view?usp=sharing

        Liked by 1 person

  10. UI.MultipleInputForm ++ – data|shapes Avatar
    UI.MultipleInputForm ++ – data|shapes

    […] may have the exact same purpose as the previous UI.MultipleInputForm (which still works like this), but it allows more customization and offers the possibility to use ListView inputs. […]

    Like

  11. Marcel Rijsmus Avatar
    Marcel Rijsmus

    It would be nice to be able to start excel, do some computations and bring the calculated value or values back as inputs or somethink like that.

    I like your work, thanks.
    Marcel

    Liked by 1 person

  12. Mathias Nielsen Avatar
    Mathias Nielsen

    Hi there,

    First off; what a fantastic script! With that set: Is there any way to change the width of both the window/UI menu and the input names? I managed to figure out how to adjust the height (“y”), but can’t seem to find the “x” anywhere.

    With kind regards

    Liked by 1 person

    1. data|shapes Avatar
      data|shapes

      Hi Mathias,
      thanks for your message! If you want to modify the width of the label width you need to change the value on line 110 “label.Width = 80” .
      For the form itself, you’ll need to add a line of code after the initiation of the form (line 85) that would look like this : form.Width = [your value].

      Have a good day!

      Like

      1. Mathias Nielsen Avatar
        Mathias Nielsen

        That works perfecty! Do you know a site or search I could make in order to find more UI-customizable “settings”? Just for the visual part of the menu.

        Alot of thanks for the quick response!

        Like

      2. data|shapes Avatar
        data|shapes

        There are plenty of resources online for winforms. Most of them are in C# but it’s not too complicated to deduce how to do it in python. You should also check out UI.MultipleInputForm ++ : https://data-shapes.net/2016/12/13/ui-multipleinputform/

        Like

  13. A Lejandro Bravo Avatar
    A Lejandro Bravo

    Hi !

    I have had run the script correctly . But the problem is that the parameter that I loaded doesnt appear in the selected Category . I tried to loaded manually but appears the revit window : The selected parameter has already been added.

    Then I have look into Project Parameters and click modify . I have notice that the parameter is loaded with the right group parameter but not with the Category which I selected to be loaded . The selected category doesnt appear in the Category list .

    Have a good day!
    Alejandro

    Like

    1. data|shapes Avatar
      data|shapes

      Hi Alejandro,
      Thanks for your comment sorry for the very late reply.
      You’re referring to the “batch add shared paramters script” right?
      What version of Revit/Dynamo are you using and what category/group are you trying to add the parameters to ?

      Like

  14. Arjay Avatar
    Arjay

    Hi Data Shapes. Good day. First I want to say great stuff you got here. Secondly, I was hoping you could add a feature wherein I can select a face from a link, or it there any existing already, can you assist me help get through this? Thank you very much.

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Latest Articles