Extending the power of LISP through .NET
I think it would be good to start a thread on adding functionality to LISP from .NET.
This is like the wishlist.
What functionality would you like to see in LISP that .NET has?
Or just general wishes.
I prefer to write code in VB.NET but I think the solutions should be in both.
We are all programmers, so LISP is the topic... but the code will be in other languages.
Also general template files and 2012 vb.net c# express editors download links would be useful.
Ideas?
P=
Re: Extending the power of LISP through .NET
Viewports cannot be modified in lisp. Is it possible in NET? Functions to set Height, Width, Center, etc... would be nice. A library of yours which adds lisp functions saved somewhere we could check for updates would be even better. Some type of help file would make it perfect!
Re: Extending the power of LISP through .NET
Well using activeX you can change some of the properties of viewports
(vla-put-width objViewport 1.0)
Works
But just to start the conversation...
Using VB.Net the following also works to change the width of a viewport.
Code:
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Runtime
Public Class LISPClass
' syntax (ViewportWidthPut (entlast) 10.0)
<LispFunction("ViewportWidthPut")> _
Public Function ViewportWidthPut(ByVal rbfLISPArguments As ResultBuffer)
On Error GoTo OnError
Dim arrLISPArguments As TypedValue() = rbfLISPArguments.AsArray
If arrLISPArguments.Length = 2 Then
Dim oidSelection As ObjectId = arrLISPArguments(0).Value
Dim dblWidth As Double = arrLISPArguments(1).Value
Dim objDocument As Document = Application.DocumentManager.MdiActiveDocument
Using objTransaction As Transaction = objDocument.Database.TransactionManager.StartTransaction()
Dim objViewport As Viewport = CType(oidSelection.GetObject(OpenMode.ForWrite), Viewport)
objViewport.Width = dblWidth
objTransaction.Commit()
End Using
Return New TypedValue(LispDataType.T_atom, -1)
End If
OnError: Return New TypedValue(LispDataType.Nil, -1)
End Function
End Class
Re: Extending the power of LISP through .NET
Quote:
Originally Posted by
Tom Beauford
Viewports cannot be modified in lisp. Is it possible in NET? Functions to set Height, Width, Center, etc... would be nice. A library of yours which adds lisp functions saved somewhere we could check for updates would be even better. Some type of help file would make it perfect!
Here's a loosely related example of a .NET LispFunction Method, which modifies the Active Page Setup of a given Layout... Downloadable files here:
http://forums.augi.com/showthread.ph...=1#post1219546
Quote:
Quote:
Originally Posted by
BlackBox
Building on my earlier post, here's an incremental update which makes available a LispFunction Method named
vla-SetActivePageSetup.
A help file for this function is attached to the bottom of this post. 2011 .chm colors used. The help file is in HTM format, but a .TXT extension has been added, as .HTM is not a supported upload file format here at AUGI.
Please note that while I have tested this enough to determine that it functions as designed (tested for 2010-2012, using Civil 3D), I have not yet had an opportunity to test this via ObjectDBX, etc., so constructive criticism is welcomed.
vla-SetActivePageSetup
Sets a named page setup active for a given layout by name
Code:
(vla-SetActivePageSetup layoutName pageSetupName)
Arguments
layoutName
A string specifying the name of a layout to apply the named page setup.
pageSetupName
A string specifying the page setup to apply to the layout.
Return Values
Nil if either the
layoutName, or
pageSetupName cannot be found. Otherwise,
T if successful.
Example
Code:
(foreach layoutname (layoutlist)
(vla-SetActivePageSetup layoutname “YourPageSetupName”)
)
Like me, most of you would prefer to compile the .NET assembly yourself, so here's the source code for your use:
Code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly: CommandClass(typeof(BlackBox.AutoCAD.PageSetup.Commands))]
namespace BlackBox.AutoCAD.PageSetup
{
public class Commands
{
[LispFunction("vla-SetActivePageSetup")]
public bool vlaSetActivePageSetup(ResultBuffer resbuf)
{
Document doc = acApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
bool ret = false;
try
{
if (resbuf == null)
throw new TooFewArgsException();
TypedValue[] args = resbuf.AsArray();
if (args.Length < 1)
throw new TooFewArgsException();
if (args.Length > 2)
throw new TooManyArgsException();
if (args[0].TypeCode != (int)LispDataType.Text)
throw new ArgumentTypeException("stringp", args[0]);
if (args.Length == 2 && args[1].TypeCode != (int)LispDataType.Text)
throw new ArgumentTypeException("stringp", args[1]);
string layoutName = args[0].Value.ToString().ToUpper();
string pageSetupName = args[1].Value.ToString().ToUpper();
using (DocumentLock dl = doc.LockDocument())
{
using (Transaction tr =
doc.Database.TransactionManager.StartOpenCloseTransaction())
{
DBDictionary layoutDic =
tr.GetObject(doc.Database.LayoutDictionaryId,
OpenMode.ForRead, false) as DBDictionary;
if (layoutDic != null)
{
foreach (DBDictionaryEntry entry in layoutDic)
{
Layout layout =
tr.GetObject(entry.Value,
OpenMode.ForRead) as Layout;
if (layout != null &&
layout.LayoutName.ToUpper() == layoutName)
{
DBDictionary acPlotSettings =
tr.GetObject(db.PlotSettingsDictionaryId,
OpenMode.ForRead) as DBDictionary;
if (acPlotSettings.Contains(pageSetupName))
{
PlotSettings ps =
(PlotSettings)tr.GetObject(
acPlotSettings.GetAt(pageSetupName), OpenMode.ForRead);
layout.UpgradeOpen();
layout.CopyFrom(ps);
ret = true;
}
}
}
}
tr.Commit();
}
}
}
catch (LispException ex)
{
doc.Editor.WriteMessage("\n; error: LispException: " + ex.Message);
}
catch (System.Exception ex)
{
doc.Editor.WriteMessage("\n; error: System.Exception: " + ex.Message);
}
return ret;
}
}
// Special thanks to Gile, for his work on the following Exception helpers
class LispException : System.Exception
{
public LispException(string msg) : base(msg) { }
}
class TooFewArgsException : LispException
{
public TooFewArgsException() : base("too few arguments") { }
}
class TooManyArgsException : LispException
{
public TooManyArgsException() : base("too many arguments") { }
}
class ArgumentTypeException : LispException
{
public ArgumentTypeException(string s, TypedValue tv)
: base(string.Format(
"invalid argument type: {0}: {1}",
s, tv.TypeCode == (int)LispDataType.Nil ? "nil" : tv.Value))
{ }
}
}
Re: Extending the power of LISP through .NET
Peter,
I have a small library of LispFunctions I use, or have coded for others... At one point I started to compile them into a single Visual LISP Xpanded (VLX) project (to be punny)... When I have some time (over the Christmas break?), I'll try to post some.
Cheers
[Edit] - I've made this thread a sticky for the time being; it is unique from the other LISP threads. I'll clean it up if it gets too cluttered.
Re: Extending the power of LISP through .NET
I prefer to code the solution myself... Although I do look for examples sometimes...
It's like having someone else solve your Soduko puzzle
Here are two general functions to get and put .net properties from lisp using .net.
Code:
Imports System
Imports System.Reflection
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Runtime
Public Class LISPClass
' syntax (PropertyPut (entlast) "width" 10.0)
<LispFunction("PropertyPut")> _
Public Function PropertyPut(ByVal rbfLISPArguments As ResultBuffer)
On Error GoTo OnError
Dim arrLISPArguments As TypedValue() = rbfLISPArguments.AsArray
If arrLISPArguments.Length = 3 Then
Dim oidSelection As ObjectId = arrLISPArguments(0).Value
Dim strPropertyName As String = arrLISPArguments(1).Value
Dim objValue As Object = arrLISPArguments(2).Value
Dim objDocument As Document = Application.DocumentManager.MdiActiveDocument
Using objTransaction As Transaction = objDocument.Database.TransactionManager.StartTransaction()
Dim objSelection As Entity = CType(oidSelection.GetObject(OpenMode.ForWrite), Entity)
Dim lstProperties As IList(Of PropertyInfo) = New List(Of PropertyInfo)(objSelection.GetType().GetProperties())
Dim intIndex As Integer = PropertyInfoAvailable(lstProperties, strPropertyName)
If Not intIndex = Nothing Then
Dim infProperty As PropertyInfo = lstProperties.Item(intIndex)
If infProperty.CanRead = True And infProperty.CanWrite = True Then
infProperty.SetValue(objSelection, objValue, Nothing)
objTransaction.Commit()
objTransaction.Dispose()
Return New TypedValue(LispDataType.T_atom, -1)
End If
End If
objTransaction.Dispose()
End Using
End If
OnError: Return New TypedValue(LispDataType.Nil, -1)
End Function
' syntax (PropertyGet (entlast) "width")
<LispFunction("PropertyGet")> _
Public Function PropertyGet(ByVal rbfLISPArguments As ResultBuffer)
On Error GoTo OnError
Dim arrLISPArguments As TypedValue() = rbfLISPArguments.AsArray
If arrLISPArguments.Length = 2 Then
Dim oidSelection As ObjectId = arrLISPArguments(0).Value
Dim strPropertyName As String = arrLISPArguments(1).Value
Dim objDocument As Document = Application.DocumentManager.MdiActiveDocument
Using objTransaction As Transaction = objDocument.Database.TransactionManager.StartTransaction()
Dim objSelection As Entity = CType(oidSelection.GetObject(OpenMode.ForRead), Entity)
Dim lstProperties As IList(Of PropertyInfo) = New List(Of PropertyInfo)(objSelection.GetType().GetProperties())
Dim intIndex As Integer = PropertyInfoAvailable(lstProperties, strPropertyName)
If Not intIndex = Nothing Then
Dim infProperty As PropertyInfo = lstProperties.Item(intIndex)
If infProperty.CanRead = True And infProperty.CanWrite = True Then
Dim objValue As Object = infProperty.GetValue(objSelection, Nothing, Nothing, Nothing, Nothing)
objTransaction.Commit()
objTransaction.Dispose()
Return objValue
End If
End If
objTransaction.Dispose()
End Using
End If
OnError: Return New TypedValue(LispDataType.Nil, -1)
End Function
Public Shared Function PropertyInfoAvailable(ByVal lstProperties As IList(Of PropertyInfo), ByVal strProperty As String)
On Error GoTo OnError
For Each infProperty As PropertyInfo In lstProperties
If infProperty.Name.ToString.ToUpper = strProperty.ToUpper Then
Return lstProperties.IndexOf(infProperty)
End If
Next
OnError: Return Nothing
End Function
It is a place to start.
Re: Extending the power of LISP through .NET
Unless being done as purely a learning example (which would make sense), how is this different from Vital(?) LISP syntax?
Code:
(vlax-put <Object> <Property> <Value>)
(vlax-get <Object> <Property>)
Cheers
Re: Extending the power of LISP through .NET
Well it is similar except it does not change "com" properties. (Like Color is a com property)
It changes .net properties. (Although Color is a .net property, Colorindex is the corresponding property)
Also it is intended to make multiple function calls in the same transaction.
vital lisp uses the com and initiates one call per transaction.
When this function could be used multiple times inside one transaction.
When you make multiple calls it can drastically affect performance.
P=
Re: Extending the power of LISP through .NET
I was thinking a better name might be
LISP Extensions (VB.NET, C# and ARX)
Peter
Re: Extending the power of LISP through .NET
For those who want to participate and play with these code examples
You can download Visual Studio Express 2013 for free!
http://www.microsoft.com/en-us/downl....aspx?id=40787
I will try to find some template files for you to play with.