Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
code for customizable form creation with dynamo, Data-Shapes package
#Copyright (c) mostafa el ayoubi , 2016
#Data-Shapes www.data-shapes.net , elayoubi.mostafa@gmail.com
import clr
try:
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
from System.Drawing import Point , Size , Graphics, Bitmap, Image, Font, FontStyle, Icon, Color
from System.Windows.Forms import Application, Button, Form, Label, ColumnHeader, TextBox, CheckBox, FolderBrowserDialog, OpenFileDialog, DialogResult, ComboBox, FormBorderStyle, ListView, ListViewItem , SortOrder, Panel, ImageLayout, GroupBox
from System.Collections.Generic import *
from System.Windows.Forms import View as vi
clr.AddReference('System')
from System import IntPtr
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import Selection
importcolorselection = 0
try:
from Autodesk.Revit.UI import ColorSelectionDialog
except:
importcolorselection = 1
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
#getting screen resolution and creating resolution factor to handle high res screens
import ctypes
user32 = ctypes.windll.user32
resolutionX = user32.GetSystemMetrics(0)
resolutionY = user32.GetSystemMetrics(1)
resfactX = resolutionX/1920
resfactY = resolutionY/1080
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:
key = f.Text
self.values.append(f.Tag[key])
if f.GetType() == mylistview:
self.values.append([f.Values[i.Text] for i in f.CheckedItems])
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 colorpicker(self, sender, event):
dialog = ColorSelectionDialog()
selection = ColorSelectionDialog.Show(dialog)
selected = dialog.SelectedColor
sender.Tag = selected
sender.BackColor = Color.FromArgb(selected.Red,selected.Green,selected.Blue)
sender.ForeColor = Color.FromArgb(selected.Red,selected.Green,selected.Blue)
def topmost(self):
self.TopMost = True
def lvadd(self, sender, event):
sender.Tag = [i for i in sender.CheckedItems]
class mylistview(ListView):
def __init__(self):
self.Values = []
#Form initialization
form = MultiTextBoxForm()
form.topmost()
xlabel = 25*resfactX
xinput = 150*resfactX
y = 10*resfactY
inputheight = 20*resfactY
inputwidth = 160*resfactX
fields = []
error = 0
#Description
if IN[3] != "":
des = Label()
des.Font = Font("Arial", 15,FontStyle.Bold)
des.Location = Point(xlabel,y)
des.AutoSize = True
des.MaximumSize = Size(300*resfactX,0)
des.Text = IN[3]
form.Controls.Add(des)
y = des.Bottom + 40*resfactY
#Input form
if isinstance(IN[0],list):
inputtypes = IN[0]
else:
inputtypes = [IN[0]]
for j in inputtypes:
label = Label()
label.Location = Point(xlabel,y+4)
label.AutoSize = True
label.MaximumSize = Size(120*resfactX,0)
label.Text = j.inputname
form.Controls.Add(label)
if j.__class__.__name__ == 'dropdown':
cb = ComboBox()
cb.Location = Point(xinput,y)
cb.Width = inputwidth
cb.Height = inputheight
[cb.Items.Add(i) for i in j.keys() if not (i == 'inputname' or i == 'height')]
cb.Tag = j
form.Controls.Add(cb)
form.output.append(cb)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'listview':
lv = mylistview()
lv.Values = j
lv.CheckBoxes = True
lv.View = vi.List
lv.Sorting = SortOrder.Ascending
[lv.Items.Add(i) for i in j.keys() if not (i == 'inputname' or i == 'height')]
lv.Location = Point(xinput,y)
lv.Width = inputwidth
lv.Height = j.height
lv.Scrollable = True
form.Controls.Add(lv)
form.output.append(lv)
y = lv.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uitext':
tb = TextBox()
tb.Text = j.defaultvalue
tb.Width = inputwidth
tb.Height = inputheight
tb.Location = Point(xinput,y)
form.Controls.Add(tb)
form.Controls.Add(label)
form.output.append(tb)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uitextnote':
gb = GroupBox()
gb.Text = j.title
gb.Parent = form
gb.SendToBack()
gb.BackColor = Color.Transparent
gb.Location = Point(xlabel, y)
tn = Label()
tn.Location = Point(xlabel*resfactX,18*resfactY)
tn.AutoSize = True
tn.MaximumSize = Size(260*resfactX,0)
tn.Text = j.textnote
tn.BringToFront()
gb.Controls.Add(tn)
gb.Size = Size(285*resfactX, tn.Bottom-tn.Top+25*resfactY)
y = gb.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uibool':
yn = CheckBox()
yn.Width = inputwidth
yn.Height = inputheight
yn.Location = Point(xinput,y)
yn.Text = j.booltext
yn.Checked = j.defaultvalue
form.Controls.Add(yn)
form.output.append(yn)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uifilepath':
fp = Button()
fp.Width = inputwidth
fp.Height = inputheight
fp.Text = j.defaultvalue
fp.Location = Point(xinput,y)
form.Controls.Add(fp)
fp.Click += form.openfile
form.output.append(fp)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uidirectorypath':
dp = Button()
dp.Width = inputwidth
dp.Height = inputheight
dp.Text = j.defaultvalue
dp.Location = Point(xinput,y)
form.Controls.Add(dp)
dp.Click += form.opendirectory
form.output.append(dp)
y = label.Bottom + 30*resfactY
elif j.__class__.__name__ == 'uiselectelements':
se = Button()
se.Width = inputwidth
se.Heigth = inputheight
se.Text = j.buttontext
se.Location = Point(xinput,y)
form.Controls.Add(se)
se.Click += form.pickobjects
form.output.append(se)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uiselectfaces':
sf = Button()
sf.Width = inputwidth
sf.Height = inputheight
sf.Text = j.buttontext
sf.Location = Point(xinput,y)
form.Controls.Add(sf)
sf.Click += form.pickfaces
form.output.append(sf)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uiselectedges':
sed = Button()
sed.Width = inputwidth
sed.Height = inputheight
sed.Text = j.buttontext
sed.Location = Point(xinput,y)
form.Controls.Add(sed)
sed.Click += form.pickedges
form.output.append(sed)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uicolorpick' and importcolorselection == 0:
cp = Button()
cp.Width = inputwidth
cp.Height = inputheight
cp.Text = j.buttontext
cp.Location = Point(xinput,y)
form.Controls.Add(cp)
cp.Click += form.colorpicker
form.output.append(cp)
y = label.Bottom + 25*resfactY
elif j.__class__.__name__ == 'uicolorpick' and importcolorselection == 1:
importcolorselection = 2
#Adding validation button
button = Button()
button.Text = IN[1]
button.Width = inputwidth
button.Location = Point (150*resfactX,y+60*resfactY)
button.Click += form.setclose
form.Controls.Add(button)
form.MaximizeBox = False
form.MinimizeBox = False
form.FormBorderStyle = FormBorderStyle.FixedSingle
#Adding Logo
#default logo in case no input
try:
#There won't be a default logo if your package folder is not the default one
deflogopath = os.getenv('APPDATA')+"\\Dynamo\Dynamo Revit\\1.2\packages\Data-Shapes\extra\\a.png"
if IN[4] == '':
ima = Image.FromFile(deflogopath)
else :
ima = IN[4]
logo = Panel()
logo.Size = Size(100*resfactX,100*resfactX)
ratio = (ima.Height)/(ima.Width)
h = float(ima.Height)
w = float(ima.Width)
ratio = h/w
scaledimage = Bitmap(100*resfactX,(100*ratio)*resfactY)
gr = Graphics.FromImage(scaledimage)
gr.DrawImage(ima,0,0,100*resfactX,100*ratio*resfactY)
logo.BackgroundImage = scaledimage
logo.BackgroundImageLayout = ImageLayout.Center
form.Controls.Add(logo)
logo.Location = Point(20*resfactX,y+20*resfactY)
#Setting icon
if IN[4] == '':
bmp = Bitmap.FromFile(deflogopath)
else:
bmp = Bitmap(IN[4])
thumb = bmp.GetThumbnailImage(64*resfactX, 64*resfactX, bmp.GetThumbnailImageAbort,IntPtr.Zero)
thumb.MakeTransparent();
icon = Icon.FromHandle(thumb.GetHicon())
form.Icon = icon
except:
form.ShowIcon = False
form.Height = y + 180*resfactY
form.Width = 350*resfactX
if IN[2]:
if importcolorselection != 2:
Application.Run(form)
result = form.values
OUT = result,True
else:
OUT = ['ColorSelection input is only available With Revit 2017'] , False
else :
OUT = ['Set toggle to true!'] , False
except:
import traceback
OUT = traceback.format_exc() , "error"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment