Node replacements

Dear Dynamo specialists,

I would like to have the newest version of a node (of packages) in my graph.
image.

Is there a simpeler way to change the version of the node instead of remove older version and set the lines again (time extensive)?

@rlandkroon ,

is this your won costumnode?

you can extract the pythoncode and you can maintain it.

KR

Andreas

Thanks for the response!

No, it is the node of Data-Shapes. I would like to use original packages instead of experimentation to extract codes. But I would like to replace for example version Clockwork for Dynamo node 2.3.0 for the 2.6.0 because of the cleaning of my codes.

How can I replace a 2.3.0. node, when package 2.6.0 for example is loaded, for the newest 2.6.0. node? While I dont want to remove the nodes and replace it and combine the lines of the nodes.

@rlandkroon ,

in our office we avoid packages … instead we maintain our code

#Copyright (c) Data Shapes,	 2020
#Data-Shapes www.data-shapes.io , elayoubi.mostafa@data-shapes.io @data_shapes
	
import clr
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os
import webbrowser
import unicodedata
import io
import tempfile
import System
	
try:
	clr.AddReference('System.Windows.Forms')
	clr.AddReference('System.Drawing')
	clr.AddReference('System.Windows.Forms.DataVisualization')
	clr.AddReference("PresentationCore")
	clr.AddReference("WindowsBase")
	from System.Windows.Input import  Key, Keyboard
	
	from System.Drawing import Point , Size , Graphics, Bitmap, Image, Font, FontStyle, Icon, Color, Region , Rectangle , ContentAlignment , SystemFonts, FontFamily
	from System.Windows.Forms import Application, DockStyle,MouseButtons , Button, Form, Label, TrackBar , ToolTip, ColumnHeader, TextBox, CheckBox, FolderBrowserDialog, OpenFileDialog, DialogResult, ComboBox, FormBorderStyle, FormStartPosition, ListView, ListViewItem , SortOrder, Panel, ImageLayout, GroupBox, RadioButton, BorderStyle, PictureBox, PictureBoxSizeMode, LinkLabel, CheckState, ColumnHeaderStyle , ImageList, VScrollBar, DataGridView, DataGridViewSelectionMode, DataGridViewAutoSizeColumnsMode , DataGridViewClipboardCopyMode , TreeView , TreeNode , TreeNodeCollection , AutoScaleMode , Screen, Padding, NativeWindow
	from System.Windows.Forms.DataVisualization.Charting import *#Chart , SeriesChartType
	from System.Collections.Generic import *
	from System.Collections.Generic import List as iList
	from System.Windows.Forms import View as vi
	clr.AddReference('System')
	from System import IntPtr , Char
	from System import Type as SType, IO
	from System import Array
	from System.ComponentModel import Container
	clr.AddReference('System.Data')
	from System.Data import DataTable , DataView

	try: #try to import All Revit dependencies
		clr.AddReference('RevitAPIUI')
		from  Autodesk.Revit.UI import Selection , TaskDialog 
		from  Autodesk.Revit.UI.Selection import ISelectionFilter
		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
	
		clr.AddReference('RevitAPI')
		try:
			from Autodesk.Revit.DB import ImageImportOptions	
		except:
			from Autodesk.Revit.DB import ImageTypeOptions , ImageType, ImagePlacementOptions , ImageInstance
		from Autodesk.Revit.DB import FilteredElementCollector , Transaction, View , ViewType , ViewFamily, ViewDrafting, ViewFamilyType, Element, ElementId , FamilyInstance , Document , XYZ, BoxPlacement, UnitUtils
		
		try:
			from Autodesk.Revit.DB import  UnitType
		except:
			from Autodesk.Revit.DB import SpecTypeId

		dbviews = [v for v in FilteredElementCollector(doc).OfClass(View).ToElements() if (v.ViewType == ViewType.FloorPlan or v.ViewType == ViewType.CeilingPlan or v.ViewType == ViewType.Section or v.ViewType == ViewType.Elevation or v.ViewType == ViewType.ThreeD)]
		viewindex = 0
		try:
			UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits
		except:
			UIunit = Document.GetUnits(doc).GetFormatOptions(SpecTypeId.Length).GetUnitTypeId()
			
		class selectionfilter(ISelectionFilter):
			def __init__(self,category):
				self.category = category
			def AllowElement(self,element):
				if element.Category.Name in [c.Name for c in self.category]:
					return True
				else:
					return False
			def AllowReference(reference,point):
				return False


			
	except: #in case we are in the Sandbox, Formit or Civil 3D environment
		pass
	
	importcolorselection = 0
	
	try:
		from  Autodesk.Revit.UI import ColorSelectionDialog
	except:
		importcolorselection = 1

	try:
		from  Autodesk.Revit.DB import ImageTypeSource 
	except:
		pass
	

	
	clr.AddReference('ProtoGeometry')
	from Autodesk.DesignScript.Geometry import Point as dsPoint

	from System.Reflection import Assembly
	import xml.etree.ElementTree as et
	

	
	import re	
	def regexEndNum(input):
		try:
			return	re.search('(\d+)$', input).group(0)
		except:
			return ""

	def iterateThroughNodes(collection,li):
		if hasattr(collection,'Nodes'):
			ntest = collection.Nodes
			if len(ntest) > 0:
				for i in ntest:
					iterateThroughNodes(i,li)
			else:
				if collection.Checked:
					li.append(collection.Tag)
		return li

	class CustomMessageLoop(NativeWindow):
	    def __init__(self, form):
	        self.form = form
	        self.AssignHandle(form.Handle)
	        self.run_loop()
	
	    def run_loop(self):
	        while self.form.Visible:
	            Application.DoEvents()

	
	class MultiTextBoxForm(Form):
		
		def __init__(self):
			self.Text = 'Data-Shapes | Multi Input UI ++'
			self.output = []
			self.values = []
			self.cancelled = True
			self.lastMouseLocation = 0
			self.startNode = None
	
		def setclose(self, sender, event):
			cbindexread = 0
			if sender.Name != "Cancel":
				self.cancelled = False
				for f in self.output:					
					if f.GetType() == myTextBox:
						if f._isNum :
							val = float(f.Text)
						else:
							val = f.Text
						self.values.append(val)
					if f.GetType() == CheckBox:
						self.values.append(f.Checked)
					if f.GetType() == Button:
						if isinstance(f.Tag ,list):
							try:
								self.values.append([e for e in f.Tag if e.__class__.__name__ != "Category"])							
							except:
								self.values.append(f.Tag)							
						else:
							try:						
								if f.Tag.__class__.__name__ != "Category":
									self.values.append(f.Tag)
								else:
									self.values.append([])
							except:
								self.values.append(f.Tag)	
					if f.GetType() == ComboBox:
						try:
							key = f.Text
							self.values.append(f.Tag[key])
						except:
							self.values.append(None)
					if f.GetType() == mylistview:
						self.values.append([f.Values[i.Text] for i in f.CheckedItems])
					if f.GetType() == mytrackbar:
						self.values.append(f.startval+f.Value*f.step)
					if f.GetType() == mygroupbox:
						try:
							key = [j.Text for j in f.Controls if j.Checked == True][0]
							self.values.append(f.Tag[key])
						except:
							self.values.append(None)
					if f.GetType() == myDataGridView:
						f.EndEdit()
						dsrc = f.DataSource
						out = []
						colcount = f.ColumnCount
						rowcount = f.RowCount - 1
						if f.Tag:
							l = []
							for i in range(colcount):								
								l.append(dsrc.Columns[i].ColumnName)
							out.append(l)								
							for r in range(rowcount):
								l = []
								for i in range(colcount):
									l.append(dsrc.DefaultView[r].Row[i])
								out.append(l)
						else: 
							for r in range(rowcount):
								l = []
								for i in range(colcount):
									l.append(dsrc.DefaultView[r].Row[i])
								out.append(l)
						self.values.append(out)
					if f.GetType() == TreeView:
						ls = []
						nds = f.Nodes[0]
						iterateThroughNodes(nds,ls)
						self.values.append(ls)
					if f.GetType() == GroupBox:
						rb = [c for c in f.Controls if c.GetType() == RadioButton and c.Checked][0]
						self.values.append(rb.Text)
						f.Controls.Remove(rb)
			else:
				self.values = None
				self.cancelled = True
			try:
				self.Close()
			except:
				Console.WriteLine("error")
	
		def reset(self, sender, event):
			pass
	
		def openfile(self, sender, event):
			ofd = OpenFileDialog()
			dr = ofd.ShowDialog()
			if dr == DialogResult.OK:
				sender.Text = ofd.FileName
				sender.Tag = ofd.FileName

		def exportToExcel(self, sender, event):
			#importing Excel IronPython libraries
			clr.AddReferenceByName('Microsoft.Office.Interop.Excel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c')
			from Microsoft.Office.Interop import Excel
			ex = Excel.ApplicationClass()
			ex.Visible = sender.Tag[1]
			ex.DisplayAlerts = False
			fbd = FolderBrowserDialog()
			fbd.SelectedPath = sender.Text
			parent = sender.Parent
			fptextbox = parent.GetChildAtPoint(Point(parent.Location.X,sender.Location.Y+5*yRatio))
			dataGrid = parent.GetChildAtPoint(Point(parent.Location.X,parent.Location.Y+23*xRatio))
			dataTable = dataGrid.DataSource
			fptext = fptextbox.Text
			titletext = parent.GetChildAtPoint(Point(0,0)).Text
			dr = fbd.ShowDialog()
			frstRwTtle = sender.Tag[0]
			if frstRwTtle:
				_header = Excel.XlYesNoGuess.xlYes
			else:
				_header = Excel.XlYesNoGuess.xlNo
			if dr == DialogResult.OK:
				workbk = ex.Workbooks.Add()
				worksheet = workbk.Worksheets.Add()
				#Writing title and doc info
				if sender.Tag[2]:
					titleCell = worksheet.Cells[1,1]
					worksheet.Cells[2,1].Value2 = sender.Tag[3]
					titleCell.Value2 = titletext
					titleCell.Font.Size = 18
					titleCell.Font.Bold = True
					startR = 3
					endR = 3
				else:
					startR = 1
					endR = 0	
				if frstRwTtle:
					for j in range(0,dataTable.Columns.Count):
						worksheet.Cells[startR,j+1] = dataTable.Columns[j].ColumnName				
					for i in range(0,dataTable.Rows.Count):
						for j in range(0,dataTable.Columns.Count):
							worksheet.Cells[i+startR+1,j+1] = dataTable.DefaultView[i].Row[j].ToString()
					xlrange = ex.get_Range(worksheet.Cells[startR,1],worksheet.Cells[dataTable.Rows.Count+endR+1,dataTable.Columns.Count])							
				else :
					for i in range(0,dataTable.Rows.Count):
						for j in range(0,dataTable.Columns.Count):
							worksheet.Cells[i+startR,j+1] = dataTable.DefaultView[i].Row[j].ToString()				
					xlrange = ex.get_Range(worksheet.Cells[startR,1],worksheet.Cells[dataTable.Rows.Count+endR,dataTable.Columns.Count])
				xlrange.Columns.AutoFit()
				worksheet.ListObjects.Add(Excel.XlListObjectSourceType.xlSrcRange, xlrange, SType.Missing, _header, SType.Missing).Name = "DataShapesTable"
				worksheet.ListObjects["DataShapesTable"].TableStyle =  "TableStyleMedium16"
				workbk.SaveAs(fbd.SelectedPath + "\\" + fptext)
				if not sender.Tag[1]:
					workbk.Close()
					ex.Quit()

		def startCell(self, sender, event ):
			sender.startcell["X"] = event.ColumnIndex
			sender.startcell["Y"] = event.RowIndex	

		def endCell(self, sender, event ):
			try:
				sender.endcell["X"] = event.ColumnIndex
				sender.endcell["Y"] = event.RowIndex 
				startval = sender.Rows[sender.startcell["Y"]].Cells[sender.startcell["X"]].Value
				endNum = regexEndNum(startval)
				if endNum != "":
					if sender.endcell["Y"] == sender.startcell["Y"]:
						for e,i in enumerate(range(sender.startcell["X"],sender.endcell["X"] + 1)):
							sender.Rows[sender.startcell["Y"]].Cells[i].Value = startval[:-len(endNum)] + str(int(endNum) + e)
					elif sender.endcell["X"] == sender.startcell["X"]:
						for e,i in enumerate(range(sender.startcell["Y"],sender.endcell["Y"] + 1)):
							sender.Rows[i].Cells[sender.endcell["X"]].Value = startval[:-len(endNum)] + str(int(endNum) + e)
				else:				
					if sender.endcell["Y"] == sender.startcell["Y"]:
						for i in range(sender.startcell["X"],sender.endcell["X"] + 1):
							sender.Rows[sender.startcell["Y"]].Cells[i].Value = startval
					elif sender.endcell["X"] == sender.startcell["X"]:
						for i in range(sender.startcell["Y"],sender.endcell["Y"] + 1):
							sender.Rows[i].Cells[sender.endcell["X"]].Value = startval
			except:
				pass
						
		def startRowDrag(self, sender, event ):
			shmak
			
		def opendirectory(self, sender, event):
			fbd = FolderBrowserDialog()
			fbd.SelectedPath = sender.Text
			dr = fbd.ShowDialog()
			if dr == DialogResult.OK:
				sender.Text = fbd.SelectedPath
				sender.Tag = fbd.SelectedPath
	
		def pickobjects(self, sender, event):	
			for c in self.Controls:
				c.Enabled = False
			try:
				sel = uidoc.Selection.PickObjects(Selection.ObjectType.Element,'')
				selelem = [doc.GetElement(s.ElementId) for s in sel]
				sender.Tag = (selelem)
			except:
				pass
			for c in self.Controls:
				c.Enabled = True
		#THIS METHOD IS FOR CIVIL 3D EVIRONMENT
		def pickautocadobjects(self, sender, event):   
			selelem = []	
			for c in self.Controls:
				c.Enabled = False
			try:
				acadDoc = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application").ActiveDocument
				acadDoc.Activate()
				acadUser = acadDoc.GetVariable("users5")	
				acadDoc.SendCommand("(and(princ\042"+ sender.Text + "\042)(setq ss(ssget))(setvar\042users5\042\042LinkDWGUIOK\042)(command\042_.Select\042ss\042\042)) ")
				selection_ = acadDoc.ActiveSelectionSet
				acadDoc.SendCommand("(setq ss nil) ")
				if acadDoc.GetVariable("users5") == "LinkDWGUIOK" and selection_ != None:
					for sel in selection_:				
						selelem.append(sel)		
					acadDoc.SetVariable("users5", acadUser)
				sender.Tag = list(selelem)		
			except:
				pass
			for c in self.Controls:
				c.Enabled = True	

		def pickautocadobject(self, sender, event):	  
			selelem = None	
			for c in self.Controls:
				c.Enabled = False
			try:
				acadDoc = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application").ActiveDocument
				acadUser = acadDoc.GetVariable("users5")
				acadPickBox = acadDoc.GetVariable("pickbox")
				acadDoc.SetVariable("pickbox", 5)
				acadDoc.Activate()
				acadDoc.SendCommand("(setq obj(car(entsel\042" + sender.Text + "\042))) ")
				acadDoc.SendCommand("(and obj(setvar\042users5\042(cdr(assoc 5(entget obj))))(setq obj nil)) ")		
				selection_ = acadDoc.GetVariable("users5")
				acadDoc.SetVariable("pickbox", acadPickBox)
				acadDoc.SetVariable("users5", acadUser)
				selelem = acadDoc.HandleToObject(selection_)
				sender.Tag = selelem		
			except:
				pass
			for c in self.Controls:
				c.Enabled = True	

		def pickobjectsordered(self, sender, event):
			for c in self.Controls:
				c.Enabled = False
			output = []
			test = True
			TaskDialog.Show("Data|Shapes", 'Pick elements in order, then hit ESC to exit.')
			while test:
				try:
					sel = doc.GetElement(uidoc.Selection.PickObject(Selection.ObjectType.Element, 'Pick elements in order').ElementId)
					output.append(sel.ToDSType(True))
				except : 
					test = False
				sender.Tag = output
			for c in self.Controls:
				c.Enabled = True
		
		def pickobjectsofcatordered(self, sender, event):
			for c in self.Controls:
				c.Enabled = False
			output = []
			test = True
			if isinstance(sender.Tag,list):			
				category = UnwrapElement(sender.Tag)
			else:
				category = [UnwrapElement(sender.Tag)]
			TaskDialog.Show("Data|Shapes", 'Select %s in order, then press ESC to exit.' %(', '.join([c.Name for c in category])))
			while test:
				try:
					selfilt = selectionfilter(category)
					sel = doc.GetElement(uidoc.Selection.PickObject(Selection.ObjectType.Element,selfilt, 'Select %s' %(', '.join([c.Name for c in category]))).ElementId)				
					output.append(sel.ToDSType(True))
				except : 
					test = False
				sender.Tag = (output)
			for c in self.Controls:
				c.Enabled = True
			
		def picklinkedobjects(self, sender, event):
			#This part was made easier by Dimitar Venkov's work
			for c in self.Controls:
				c.Enabled = False
			try:
				linkref = uidoc.Selection.PickObject(Selection.ObjectType.Element,'Select the link instance.')
				link = doc.GetElement(linkref.ElementId).GetLinkDocument()
				td = TaskDialog.Show('Data-Shapes','Select the linked elements and press Finish.')
				sel = uidoc.Selection.PickObjects(Selection.ObjectType.LinkedElement,'Select the linked elements and press Finish.')
				selelem = [link.GetElement(s.LinkedElementId) for s in sel]
				sender.Tag = (selelem)
			except:
				pass
			for c in self.Controls:
				c.Enabled = True		

		def pickobject(self, sender, event):
			for c in self.Controls:
				c.Enabled = False
			try:
				sel = uidoc.Selection.PickObject(Selection.ObjectType.Element,'')
				selelem = doc.GetElement(sel.ElementId) 
				sender.Tag = (selelem)
			except:
				pass
			for c in self.Controls:
				c.Enabled = True
			
		def picklinkedobject(self, sender, event):
			#This part was made easier by Dimitar Venkov's work
			for c in self.Controls:
				c.Enabled = False
			try:
				linkref = uidoc.Selection.PickObject(Selection.ObjectType.Element,'Select the link instance.')
				link = doc.GetElement(linkref.ElementId).GetLinkDocument()
				td = TaskDialog.Show('Data-Shapes','Select the linked element.')
				sel = uidoc.Selection.PickObject(Selection.ObjectType.LinkedElement,'Select the linked element.')
				selelem = link.GetElement(sel.LinkedElementId)
				sender.Tag = (selelem)
			except:
				pass				
			for c in self.Controls:
				c.Enabled = True
			
		def pickobjectsofcat(self, sender, event):
			for c in self.Controls:
				c.Enabled = False
			if isinstance(sender.Tag,list):		
				category = UnwrapElement(sender.Tag)
			else:
				category = [UnwrapElement(sender.Tag)]
			try:
				selfilt = selectionfilter(category)
				sel = uidoc.Selection.PickObjects(Selection.ObjectType.Element,selfilt,'Select %s' %(', '.join([c.Name for c in category])))
				selelem = [doc.GetElement(s.ElementId) for s in sel]
				sender.Tag = (selelem)
			except:
				pass
			for c in self.Controls:
				c.Enabled = True

		def pickobjectofcat(self, sender, event):
			for c in self.Controls:
				c.Enabled = False
			if isinstance(sender.Tag,list):		
				category = UnwrapElement(sender.Tag)
			else:
				category = [UnwrapElement(sender.Tag)]
			try:
				selfilt = selectionfilter(category)
				sel = uidoc.Selection.PickObject(Selection.ObjectType.Element,selfilt,'Select %s' %(', '.join([c.Name for c in category])))
				selelem = doc.GetElement(sel.ElementId) 
				sender.Tag = (selelem)
			except:
				pass
			for c in self.Controls:
				c.Enabled = True

		def treeNodeMouseDown(self, sender, event):
			if Keyboard.IsKeyDown(Key.LeftShift) and event.Button == MouseButtons.Left:
				tv = sender
				endNode = tv.GetNodeAt(0, event.Y)
				#If both nodes exist and are in the same parent node
				if self.startNode != None and endNode != None and self.startNode.Parent == endNode.Parent:
					startIndex = self.startNode.Index
					endIndex = endNode.Index
					#Swap the indexes if the starting index is greater than the ending index
					if startIndex > endIndex:
						temp = startIndex
						startIndex = endIndex
						endIndex = temp
					for i in range(startIndex,endIndex+1):					  
						self.startNode.Parent.Nodes[i].Checked = not self.startNode.Parent.Nodes[i].Checked
					self.lastMouseLocation = event.Y
			else:
				tv = sender
				self.startNode = tv.GetNodeAt(0, event.Y)
				
				
			
		def pickfaces(self, sender, event):
			faces = []			
			for c in self.Controls:
				c.Enabled = False
			try:
				selface = uidoc.Selection.PickObjects(Selection.ObjectType.Face,'')
				for s in selface:
					elemid = s.ElementId
					elem = doc.GetElement(elemid)
					if isinstance(elem,FamilyInstance):
						transf = elem.GetTransform().ToCoordinateSystem()
						geom = elem.GetGeometryObjectFromReference(s)
						convertedGeom = geom.Convert(s, transf)					
						faces.append(convertedGeom)
					else:
						f = uidoc.Document.GetElement(s).GetGeometryObjectFromReference(s).ToProtoType(True)
						[i.Tags.AddTag("RevitFaceReference", s) for i in f]
						faces.append(f)
				sender.Tag = [i for j in faces for i in j]
			except:
				pass
			for c in self.Controls:
				c.Enabled = True
				
		def pickpointsonface(self, sender, event):
			faces = []			
			for c in self.Controls:
				c.Enabled = False
			selpoints = uidoc.Selection.PickObjects(Selection.ObjectType.PointOnElement,'')
			points = []
			for s in selpoints:
				pt = s.GlobalPoint
				points.append(dsPoint.ByCoordinates(UnitUtils.ConvertFromInternalUnits(pt.X,UIunit),UnitUtils.ConvertFromInternalUnits(pt.Y,UIunit),UnitUtils.ConvertFromInternalUnits(pt.Z,UIunit)))
			sender.Tag = points
			for c in self.Controls:
				c.Enabled = True
				
		def pickedges(self, sender, event):
			edges = []
			for c in self.Controls:
				c.Enabled = False	
			try:				
				seledge = uidoc.Selection.PickObjects(Selection.ObjectType.Edge,'')
				for s in seledge:
					elemid = s.ElementId
					elem = doc.GetElement(elemid)
					if isinstance(elem,FamilyInstance):
						transf = elem.GetTransform().ToCoordinateSystem()
						geom = elem.GetGeometryObjectFromReference(s)
						convertedGeom = geom.Convert(s, transf)
						convertedGeom.Tags.AddTag("RevitFaceReference", s)
						edges.append(convertedGeom)					
					else:
						e = uidoc.Document.GetElement(s).GetGeometryObjectFromReference(s).AsCurve().ToProtoType(True)
						e.Tags.AddTag("RevitFaceReference", s)
						edges.append(e)
				sender.Tag = edges
				
				
			except:
				pass
			for c in self.Controls:
				c.Enabled = True

		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]
			
		def scroll(self, sender, event):
			parent = sender.Parent
			child = parent.GetChildAtPoint(Point(0,5*yRatio))
			child.Text = str(sender.startval+sender.Value*sender.step)

		def openurl(self, sender, event):
			webbrowser.open(sender.Tag)
	
		def selectall(self, sender, event):
			if sender.Checked:
				parent = sender.Parent
				listview = parent.GetChildAtPoint(Point(0,0))
				for i in listview.Items:
					i.Checked = True
			else:
				pass
				
		def selectnone(self, sender, event):
			if sender.Checked:
				parent = sender.Parent
				listview = parent.GetChildAtPoint(Point(0,0))
				for i in listview.Items:
					i.Checked = False
			else:
				pass		

		def updateallnone(self, sender, event):
			try:
				parent = sender.Parent
				rball = parent.GetChildAtPoint(Point(0,sender.Height + 5*yRatio))
				rbnone = parent.GetChildAtPoint(Point(80 * xRatio,sender.Height + 5*yRatio))
				if sender.CheckedItems.Count == 0 and event.NewValue == CheckState.Unchecked:
					rbnone.Checked = False
					rball.Checked = False
				elif sender.CheckedItems.Count == sender.Items.Count and event.NewValue == CheckState.Unchecked:
					rball.Checked = False
					rbnone.Checked = False
				elif sender.CheckedItems.Count == sender.Items.Count-1 and event.NewValue == CheckState.Checked:
					rball.Checked = True
					rbnone.Checked = False
				elif sender.CheckedItems.Count == 1 and event.NewValue == CheckState.Unchecked:
					rball.Checked = False
					rbnone.Checked = True			
				else :
					rball.Checked = False
					rbnone.Checked = False
			except:
				pass

		def zoomcenter(self, sender, event ):
			if event.X > 15:		
				try:
					element = doc.GetElement(uidoc.Selection.GetElementIds()[0])
					uidoc.ShowElements(element)
				except:
					pass
			else:
				pass
				
			
		def setviewforelement(self, sender, event ):	
			if event.X > 15*xRatio:				
				try:
					item = sender.GetItemAt(event.X,event.Y).Text
					element = UnwrapElement(sender.Values[item])
					try:
						viewsforelement = [v for v in dbviews if (not v.IsTemplate) and (element.Id in [e.Id for e in FilteredElementCollector(doc,v.Id).OfClass(element.__class__).ToElements()])]
					except:
						viewsforelement = [v for v in dbviews if (not v.IsTemplate) and (element.Id in [e.Id for e in FilteredElementCollector(doc,v.Id).OfClass(FamilyInstance).ToElements()])]
					global viewindex
					dbView = viewsforelement[viewindex]
					id = [element.Id]
					icollection = iList[ElementId](id)
					uidoc.Selection.SetElementIds(icollection)
				except:
					pass
			else:		
				pass


		def CheckChildren(self, sender, event ):
			evNode = event.Node		
			checkState = evNode.Checked 
			for n in event.Node.Nodes:		
				n.Checked = checkState			
				
		def ActivateOption(self, sender, event ):
			parent = sender.Parent
			associatedControls = [p for p in parent.Controls if p.Name == sender.Text and p.GetType() == Panel][0]
			restofcontrols = [p for p in parent.Controls if p.Name != sender.Text and p.GetType() == Panel]
			if sender.Checked:
				associatedControls.Enabled = True
				for c in restofcontrols:
					c.Enabled = False
				parent.Tag = sender.Text
				
		def showtooltip(self, sender, event ):
			ttp = ToolTip()
			ttp.AutoPopDelay = 10000
			ttp.SetToolTip(sender , sender.Tag) 

		def numsOnly(self, sender, event ):
			if Char.IsDigit(event.KeyChar)==False and event.KeyChar != "." and Char.IsControl(event.KeyChar)==False:
				event.Handled = True
		
		def chart_showLabels(self, sender, event):
			cb = sender
			panelcht = sender.Parent
			chart1 = panelcht.GetChildAtPoint(Point(0,0))
			for s in chart1.Series:
				if s.ChartType == SeriesChartType.Pie:
					if cb.Checked:
						s["PieLabelStyle"] = "Inside"
					else:
						s["PieLabelStyle"] = "Disabled"
				else:
					if cb.Checked:
						s.IsValueShownAsLabel = True
					else:
						s.IsValueShownAsLabel = False
				
		def imageexport(self, sender, event):
			import datetime
			from datetime import datetime
			from RevitServices.Transactions import TransactionManager
			#Modify resolution before the render
			fontFam = FontFamily("Segoe UI Symbol")
			originalFont = Font(fontFam,8)
			panelcht = sender.Parent
			chart1 = panelcht.GetChildAtPoint(Point(0,0))
			originalTitleFont = chart1.Titles[0].Font
			originalWidth = chart1.Width
			originalHeight = chart1.Height
			chart1.Visible = False
			chart1.Dock = DockStyle.None
			chart1.Width = 2100 * 0.8
			chart1.Height = 1500 * 0.8
			chart1.ChartAreas[0].AxisX.LabelAutoFitStyle = LabelAutoFitStyles.None
			chart1.ChartAreas[0].AxisY.LabelAutoFitStyle = LabelAutoFitStyles.None
			chart1.ChartAreas[0].AxisX.LabelStyle.Font = Font(fontFam, 30)
			chart1.ChartAreas[0].AxisY.LabelStyle.Font = Font(fontFam, 30)
			chart1.ChartAreas[0].AxisX.TitleFont = Font(fontFam, 30)
			chart1.ChartAreas[0].AxisY.TitleFont = Font(fontFam, 30)
			chart1.TextAntiAliasingQuality = TextAntiAliasingQuality.High
			chart1.BackColor = Color.White
			chart1.Titles[0].Font = Font(fontFam, 32, FontStyle.Bold)
			chart1.ChartAreas[0].BackColor = Color.White
			for serie in chart1.Series:
				serie.Font = Font(fontFam, 30)
				for p in serie.Points:
					p.Font = Font(fontFam, 30)
					p.MarkerSize = 15
			for legend in chart1.Legends:
				legend.Font = Font(fontFam, 30)
				legend.BackColor = Color.White
			chart1.Invalidate()
			chart1.SaveImage(tempfile.gettempdir() + "\\chartImage.bmp", ChartImageFormat.Bmp)
			#Get back to original settings
			chart1.Width = originalWidth
			chart1.Height = originalHeight
			chart1.BackColor = Color.Transparent
			chart1.ChartAreas[0].BackColor = Color.Transparent
			chart1.ChartAreas[0].AxisX.LabelStyle.Font = originalFont
			chart1.ChartAreas[0].AxisY.LabelStyle.Font = originalFont
			chart1.ChartAreas[0].AxisX.TitleFont = originalFont
			chart1.ChartAreas[0].AxisY.TitleFont = originalFont
			chart1.Titles[0].Font = originalTitleFont
			for serie in chart1.Series:
				serie.Font = originalFont
				for p in serie.Points:
					p.Font = originalFont
					p.MarkerSize = 8
			for legend in chart1.Legends:
				legend.Font = originalFont
				legend.BackColor = Color.Transparent
			chart1.Invalidate()
			chart1.Visible = True
			#Import the picture in a Drafting View
			#Import the picture in a Drafting View // The try catch if for handling the fact that ImageImportOptions was deprecated in 2020 and is obsolete in 2021					  
			collector = FilteredElementCollector(doc).OfClass(ViewFamilyType)
			viewFamilyTypes = []
			for c in collector:
				if c.ViewFamily == ViewFamily.Drafting:
					viewFamilyTypes.append(c)
			viewFamilyType = viewFamilyTypes[0]
			TransactionManager.Instance.EnsureInTransaction(doc)
			draftView = ViewDrafting.Create(doc,viewFamilyType.Id)
			draftView.Name = chart1.Titles[0].Text + datetime.now().strftime(" (%m/%d/%Y, %H.%M.%S)")
			imagePath = tempfile.gettempdir() + "\\chartImage.bmp"
			newElement = clr.StrongBox[Element]()
			try:
				importOptions = ImageImportOptions()	
				importOptions.Resolution = 72
				importOptions.Placement = BoxPlacement.TopLeft				
				doc.Import(imagePath,importOptions,draftView,newElement)			
			except:
				try:
					imageTypeOption = ImageTypeOptions()   
					imageTypeOption.SetPath(imagePath)								
				except:
					imageTypeOption = ImageTypeOptions(imagePath,False,ImageTypeSource.Import)
				imageTypeOption.Resolution = 72				   
				imageType = ImageType.Create(doc,imageTypeOption)
				placementOptions = ImagePlacementOptions(XYZ(0,0,0),BoxPlacement.TopLeft)
				ImageInstance.Create(doc,draftView,imageType.Id,placementOptions)				
			TransactionManager.Instance.TransactionTaskDone()					 
		def chart_showLegend(self, sender, event ):
			cb = sender
			panelcht = sender.Parent
			chart1 = panelcht.GetChildAtPoint(Point(0,0))
			if len(chart1.Legends) <= 1:
				for legend in chart1.Legends:
					if cb.Checked:
						legend.Enabled = True
					else:
						legend.Enabled = False
			else:
				if cb.Checked:
					chart1.Legends[1].Enabled = True
				else:
					chart1.Legends[1].Enabled = False
					

	class mylistview(ListView):
	
		def __init__(self):
			self.Values = []

	class mytrackbar(TrackBar):
	
		def __init__(self,startval,step):
			self.startval = startval
			self.step = step

	class myDataGridView(DataGridView):
	
		def __init__(self):
			self.startcell = {}
			self.endcell = {}
			
	class mygroupbox(GroupBox):
	
		def __init__(self):
			self.Values = []
			
	class myTextBox(TextBox):
	
		def __init__(self):
			self._isNum = False
	
			
	#Form initialization
	
	form = MultiTextBoxForm()
	xRatio = Screen.PrimaryScreen.Bounds.Width/1920
	if xRatio == 0:
		xRatio = 1
	yRatio = Screen.PrimaryScreen.Bounds.Height/1080
	if yRatio == 0:
		yRatio = 1
	form.topmost()	
	form.ControlBox = True
	xlabel = 25 * xRatio
	xinput = 150 * xRatio
	formy = 10 * yRatio
	if IN[8] * xRatio > (350 * xRatio): formwidth = IN[8] * xRatio
	else: formwidth = 350 * xRatio
	fields = []
	error = 0
	
	#Description 
	
	if IN[3] != "":
		des = Label()
		des.Location = Point(xlabel,formy)
		des.Font = Font("Arial", 15,FontStyle.Bold)		
		des.AutoSize = True
		des.MaximumSize = Size(formwidth - (2 * xlabel)*xRatio,0)
		des.Text = IN[3]
		form.Controls.Add(des)
		formy = des.Bottom + (15*xRatio)
	formheaderheight = formy
	
	#Input form
	
	# Create a container panel for all inputs
	body = Panel()
	body.Location = Point(0,formy)
	body.Width = formwidth - 15*xRatio
	
	
	# Process form inputs
	if isinstance(IN[0],list):
		inputtypes = IN[0]
	else:
		inputtypes = [IN[0]]
	# This definition is to handle the sorting of special characters
	def remove_accents(input_str):
		nfkd_form = unicodedata.normalize('NFKD', input_str)
		only_ascii = nfkd_form.encode('ASCII', 'ignore')
		return only_ascii	

	#Adding Logo 

		
#a.s.o.

… the code is realy long! :wink:

i can just recomment it.

KR

Andreas

It’s unclear what you’re actually asking for as these two statements seem to be mutually exclusive.

You can only load one version of a package at a time, so there’s no way to have a node in a previous version when using an updated package unless you specifically copied that node outside of the package to maintain manually.

Creating a graph with the 2.3 version of a node will save the reference to that node via the package and the version that was used, but when opened with the 3.6 version of the package will load the 2.6 version of the node as long as it still exists. The warnings you get from Dynamo about nodes using different package versions is only to notify you that the functionality of the node may have changed. The current (package) version is still used.

2 Likes

That is a LOT more work and may run afoul of some licensing for packages. Best to maintain the packages and go from there.

2 Likes

Agreed on the licensing issue- but making sure everyone has the all the same packages and setup can also be a maintenance headache in it’s own right.

Having a central location of non-package-dependent (Dynamo Player) scripts can be one way to handle it- and it’s what I have done in my office.

1 Like

The issue with this is you wind up doing the same work repeatedly.

Let’s think of this in the context of a Revit model. You have a bathroom layout which will be used in multiple times, in multiple projects, spanning multiple Revit versions. How would you go about this?

Maybe model it once and then copy it around the project, and then copy/paste to the next rvt. What about when you move into the next Revit build and the previous layout needs to change because the Revit file structure doesn’t permit hosting one of the families in the same way? And what happens when 6 months later the owner comes back and says you need to change the layout?

Utilizing groups can reduce this in the context of a single model, and if you aren’t going to reuse it content in another project it is generally recognized as a good practice, but they don’t scale to other jobs.

Utilizing an xref reduces the bulk of the rework and duplication of work issues which are prevented by the ‘copy paste instances though and across projects’ method, and is generally accepted as a best practice for reusing work at scale. However it does require updating the xref to each version, and potentially making changes in each supported project version, so maybe 4 tasks which is worse than once. But it is much better than once per instance per project (1000’s of tasks), and better than once for the group type per project (100’s of tasks).

Now let’s reframe this in the context of Dynamo.

You can copy/paste your Python into new copies of a node to make many instances of the text. And when you want to improve it or update it or alter it you have to chase them all down. Then in the next release when Revit makes a change that means you have to update the Python, that means you need to update every instance of the code. Maybe you only have one Python node per graph, but that graph has been copied and saved to multiple locations and now you need to track all of those down. And a user opening a graph with the previous version of the Python node won’t execute you have a ‘hey your dynamo thing broke’ issue to deal with, so you have to manage your .dyn versions to prevent that. Oh and you have to deal with multiple versions of the Python by managing your list structures for each.

Or you could wrap your Python in a custom node. This means you can make a change once for each Revit build, and pass that change into a new version of the package which means any .dyn with your node will work. Breaking changes mean you make one change, and updates mean you make at most 4 changes. Then deploy those to your users just like you had to with the version specific .dyn files.

Now there is an argument to say ‘one dyn version per Revit version’ consisting of a single Python node where needed, and centrally managed and deployed is easier. I’ll admit this can work for ‘one off’ tasks which won’t be replicated in other graphs, but I am not sold on you that for code which is reused. Further, if it’s one off and repeated use a full add-in is likely even easier to scale and less work than most think once you have a Python POC.

Overall we have options for ‘getting out content to users’, which is really good. However there isn’t an ‘easy button’ for management at this time. And deploying anything (.dyn or packages) at scale isn’t easy even with the package manager (warts and all I’ll take it). However in my opinion you can make your future self’s life easier by moving to packages instead of in canvas nodes.

1 Like

Two approaches I’ve experimented with (with mixed results), develop an inhouse company package and robocopy it out. You abandon using most other packages and develop your own code (I agree it’s not good to copy other package code insitu).

The other interesting approach I’ve played with is storing libraries on the server full of functions that in effect do all the work. The python code just appends them in to sys path and from there you control the function in one place. Speed hits for server storage of course though which is always rough. I used that for my logging system though, and built in a basic safeguard in the event the server could not be found using os and checking for directory path prior to appending.

One benefit was users needed to be on company system for code to function, and if they try to yoink the code it’s useless without the core libraries. Huge effort to set up and educate others in though.

1 Like

Great discussion, thank you. I know we have gotten a bit away from the original topic…
Not sure if the OP got the answer he needed from @Nick_Boyts, but the more information about pros and cons of “internal” development management out there, the better.

1 Like