using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Windows.Forms;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly
: CommandClass
(typeof(Gile
.LispTimer.LispFunctions))]
namespace Gile.LispTimer
{
public class LispFunctions
{
private Timer _timer;
private string _fun;
private int _interval;
private Document _doc;
public LispFunctions()
{
_interval = -1;
_doc = AcAp.DocumentManager.MdiActiveDocument;
AcAp.DocumentManager.DocumentCreateStarted += onActiveDocumentChanging;
AcAp.DocumentManager.DocumentToBeDeactivated += onActiveDocumentChanging;
AcAp.DocumentManager.DocumentToBeDestroyed += onActiveDocumentChanging;
}
private void StartTimer()
{
if (_timer == null && _interval > 0)
{
_timer.Interval = _interval;
_timer.Enabled = true;
_timer.Tick += OnTick;
_timer.Start();
}
}
private void CloseTimer()
{
if (_timer != null)
{
_timer.Stop();
_timer.Dispose();
_timer = null;
}
}
void OnTick(object sender, EventArgs e)
{
try
{
using (_doc.LockDocument())
{
AcAp
.Invoke(new ResultBuffer
(new TypedValue
((int)LispDataType
.Text, _fun
))); }
}
catch (System.Exception ex)
{
ShowErrorMessage(ex.Message == "eInvalidInput" ?
string.Format("Incorrect LISP function: '{0}'", _fun) :
ex.Message);
CloseTimer();
}
}
void onActiveDocumentChanging(object sender, DocumentCollectionEventArgs e)
{
CloseTimer();
}
[LispFunction("gc-TimerOn")]
public TypedValue TimerOn(ResultBuffer resbuf)
{
try
{
if (resbuf == null)
throw new TooFewArgsException
();
TypedValue[] args = resbuf.AsArray();
if (args.Length < 2)
throw new TooFewArgsException
(); if (args.Length > 2)
throw new TooManyArgsException
();
if (args[0].TypeCode != (int)LispDataType.Text)
throw new ArgumentTypeException
("stringp", args
[0]); _fun = (string)args[0].Value;
if (!args[1].TryConvertToInt(ref _interval))
throw new ArgumentTypeException
("numberp", args
[1]); _interval *= 1000;
CloseTimer();
StartTimer();
return new TypedValue
((int)LispDataType
.Nil); }
catch (System.Exception ex)
{
ShowErrorMessage("gc-TimerOn\n" + ex.Message);
throw;
}
}
[LispFunction("gc-TimerOff")]
public TypedValue TimerOff(ResultBuffer resbuf)
{
try
{
if (resbuf != null)
throw new TooManyArgsException
(); CloseTimer();
return new TypedValue
((int)LispDataType
.Nil); }
catch (System.Exception ex)
{
ShowErrorMessage("gc-TimerOff\n" + ex.Message);
throw;
}
}
private void ShowErrorMessage(string msg)
{
MessageBox.Show(
msg,
"LispTimer",
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
}
}
static class LispFunctionExtensions
{
public static bool TryConvertToInt(this TypedValue tv, ref int i)
{
if (tv.TypeCode == (int)LispDataType.Int16 ||
tv.TypeCode == (int)LispDataType.Int32)
{
i = Convert.ToInt32(tv.Value);
return true;
}
else
{
return false;
}
}
}
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 msg, TypedValue tv)
: base(string.Format(
"Bad argument type: {0}: {1}",
msg,
tv.TypeCode == (int)LispDataType.Nil ? "nil" :
tv.TypeCode == (int)LispDataType.Text ? "\"" + tv.Value + "\"" :
tv.Value))
{ }
}
}