Template= "#Crow.CheckBox2.template";
Width = "Stretched";
Height = "Fit";
- CornerRadius = "0";
+ CornerRadius = "2";
Background = "${ControlIdle}";
Foreground = "${ControlForeground}";
Checked = "{Background=${ControlHighlight}}";
MouseEnter = "{Foreground=${ControlCaptionHoverColor}}";
MouseLeave = "{Foreground=${ControlForeground}}";
}
+StateBox {
+ Template= "#Crow.CheckBox2.template";
+ Width = "Stretched";
+ Height = "Fit";
+ CornerRadius = "2";
+ Background = "${ControlIdle}";
+ Foreground = "${ControlForeground}";
+ Checked = "{Background=Green}";
+ Unchecked = "{Background=DarkRed}";
+ Focusable = "false";
+}
+
LogViewerWidget {
Background = "0.01,0.01,0.01,1";
MouseWheelSpeed = "2";
using System.Reflection;
using System.Runtime.Loader;
using System.IO;
-using System.Diagnostics;
using System.Collections.Generic;
using Crow.DebugLogger;
using System.Linq;
using CrowEditBase;
-using System.Threading;
-using Crow.Text;
-using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
using static CrowEditBase.CrowEditBase;
using Drawing2D;
+using System.Diagnostics;
namespace Crow
{
+ public class ForeignWidgetContainer {
+ Type type;
+ object instance;
+
+ }
public class CrowService : Service {
public CrowService () : base () {
restoreCrowAssemblies ();
initCommands ();
-
- crowLoadCtx = new AssemblyLoadContext("CrowDebuggerLoadContext");
-
}
public override string ConfigurationWindowPath => "#CECrowPlugin.ui.winConfiguration.crow";
dlg.DataSource = this;
}
);
+ public ActionCommand CMDOptions_RemoveCrowAssembly;
public ActionCommand CMDViewPreview;
void initCommands ()
{
CMDGotoParentEvent = new ActionCommand("parent", ()=> { CurrentEvent = CurrentEvent?.parentEvent; }, "#icons.level-up.svg", false);
CMDEventHistoryBackward = new ActionCommand("back.", currentEventHistoryGoBack, "#icons.previous.svg", false);
CMDEventHistoryForward = new ActionCommand("forw.", currentEventHistoryGoForward, "#icons.forward-arrow.svg", false);
+
+ CMDOptions_RemoveCrowAssembly = new ActionCommand ("Remove Selected Assembly", () =>
+ {
+ crowAssemblies.Remove(selectedCrowAssembly);
+ saveCrowAssemblies ();
+ }, "#icons.trash.svg", false);
}
#endregion
if (CurrentState == Status.Running)
delSetSource (imlSource);
}
+
Project activeSolution;
Exception currentException;
public string ErrorMessage = "";
Assembly crowAssembly, thisAssembly;
Type dbgIfaceType;
-#region dbgIface delegates
+
+ #region dbgIface delegates
+ Func<string,Type> delGetWidgetTypeFromName;
Action<int, int> delResize;
Func<int, int, bool> delMouseMove;
Func<float, bool> delMouseWheelChanged;
Func<ISurface> delGetMainSurface;
Action<string> delSetSource;
Action delReloadIml;
+ Action delLockRenderMutex;
+ Action delUnlockRenderMutex;
Func<double> delGetZoomFactor;
Action<double> delSetZoomFactor;
FieldInfo fiDbg_IncludedEvents, fiDbg_ConsoleOutput, fiDbgIFace_MaxLayoutingTries, fiDbgIFace_MaxDiscardCount, fiDbgIFace_Terminate;
-#endregion
+
+ //design mode members, present only if crow compiled with DESIGN_MODE enabled
+ FieldInfo fiWidget_design_id;
+ #endregion
-#region DebugLog
+ #region DebugLog
bool recording, debugLogIsEnabled;
IList<DbgEvtType> recordedEvents = new ObservableList<DbgEvtType>(new DbgEvtType[] {DbgEvtType.Widget} );
DbgEvtType addRecordedEvents = DbgEvtType.None;
NotifyValueChanged (value);
}
}
-#endregion
+ #endregion
public bool HasVkvgBackend { get; private set; }
public int RefreshRate {
if (IsRunning)
fiDbgIFace_IsDirty.SetValue (dbgIFace, false);
}
+ public void LockRenderMutex() {
+ if (IsRunning)
+ delLockRenderMutex();
+ }
+ public void UnlockRenderMutex() {
+ if (IsRunning)
+ delUnlockRenderMutex();
+ }
public bool GetDirtyState => IsRunning ? (bool)fiDbgIFace_IsDirty.GetValue (dbgIFace) : false;
+ public bool DesignModeEnabled => IsRunning && fiWidget_design_id != null ? true : false;
+ public Type GetWidgetTypeFromeName(string typeName) {
+ if (!IsRunning)
+ return null;
+ return delGetWidgetTypeFromName(typeName);
+ }
void updateCrowDebuggerState (string errorMsg = null) {
ErrorMessage = errorMsg;
ServiceIsInError = errorMsg != null;
NotifyValueChanged ("ServiceErrorMessage", (object)ErrorMessage);
NotifyValueChanged ("ServiceIsInError", ServiceIsInError);
NotifyValueChanged ("CrowAssemblyName", (object)CrowAssemblyName);
+ NotifyValueChanged ("DesignModeEnabled", DesignModeEnabled);
}
#region DesignInterface callbacks
#endregion
static string defaultCrowAssemblyLocation =>
System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Assembly.GetEntryAssembly().Location), "Crow.dll");
+
+ #region service start/stop
public override void Start()
{
if (CurrentState == Status.Running)
Recording = false;
DebugLogIsEnabled = false;
+ dbgIFace = null;
+ crowAssembly = null;
crowLoadCtx = null;
CurrentState = Status.Stopped;
+
+ updateCrowDebuggerState();
}
public override void Pause()
{
base.onStateChange(previousState, newState);
CMDRefresh.CanExecute = IsRunning;
}
-
- public Project ActiveSolution {
- get => activeSolution;
- set {
- //CERoslynPlugin.SolutionProject sol = value as CERoslynPlugin.SolutionProject;
- if (activeSolution == value)
- return;
- activeSolution = value;
- NotifyValueChanged (activeSolution);
- }
- }
+ #endregion
bool updateCrowDesignAssemblyLocation() {
if (!File.Exists (CrowDbgAssemblyLocation)) {
updateCrowDebuggerState($"Crow.dll for debugging file not found");
return false;
}
-
- if (crowAssembly != null)
- crowLoadCtx.Unload();
-
+
+ crowLoadCtx = new AssemblyLoadContext("CrowDebuggerLoadContext");
crowAssembly = crowLoadCtx.LoadFromAssemblyPath (CrowDbgAssemblyLocation);
Type debuggerType = crowAssembly.GetType("Crow.DbgLogger");
delResize = (Action<int, int>)Delegate.CreateDelegate(typeof(Action<int, int>),
dbgIFace, dbgIfaceType.GetMethod("Resize"));
- delMouseMove = (Func<int, int, bool>)Delegate.CreateDelegate(typeof(Func<int, int, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnMouseMove"));
+ delGetWidgetTypeFromName = (Func<string, Type>)Delegate.CreateDelegate(typeof(Func<string, Type>),
+ dbgIFace, dbgIfaceType.GetMethod("GetWidgetTypeFromName"));
+
+
delMouseWheelChanged = (Func<float, bool>)Delegate.CreateDelegate(typeof(Func<float, bool>),
dbgIFace, dbgIfaceType.GetMethod("OnMouseWheelChanged"));
-
+ delMouseMove = (Func<int, int, bool>)Delegate.CreateDelegate(typeof(Func<int, int, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnMouseMove"));
delMouseDown = (Func<MouseButton, bool>)Delegate.CreateDelegate(typeof(Func<MouseButton, bool>),
dbgIFace, dbgIfaceType.GetMethod("OnMouseButtonDown"));
delSetSource = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>),
dbgIFace, dbgIfaceType.GetProperty("Source").GetSetMethod());
delReloadIml = (Action)Delegate.CreateDelegate(typeof(Action), dbgIFace, dbgIfaceType.GetMethod("ReloadIml"));
+ delLockRenderMutex = (Action)Delegate.CreateDelegate(typeof(Action), dbgIFace, dbgIfaceType.GetMethod("LockRenderMutex"));
+ delUnlockRenderMutex = (Action)Delegate.CreateDelegate(typeof(Action), dbgIFace, dbgIfaceType.GetMethod("UnlockRenderMutex"));
/*delGetZoomFactor = (Func<double>)Delegate.CreateDelegate(typeof(Func<double>),
dbgIFace, dbgIfaceType.GetProperty("ZoomFactor").GetGetMethod());
fiDbgIFace_MaxLayoutingTries.SetValue (null, MaxLayoutingTries);
fiDbgIFace_MaxDiscardCount.SetValue (null, MaxDiscardCount);
+ //DESIGN_MODE only
+ Type widgetType = crowAssembly.GetType("Crow.Widget");
+ fiWidget_design_id = widgetType.GetField("design_id");
+
return true;
}
NotifyValueChanged(value);
}
}
+ public Project ActiveSolution {
+ get => activeSolution;
+ set {
+ //CERoslynPlugin.SolutionProject sol = value as CERoslynPlugin.SolutionProject;
+ if (activeSolution == value)
+ return;
+ activeSolution = value;
+ NotifyValueChanged (activeSolution);
+ }
+ }
+
+ #region Additional crow Assemblies
+ string selectedCrowAssembly = null;
//assemblies with crow resources in order of loading
IList<string> crowAssemblies = new ObservableList<string> ();
public IList<string> CrowAssemblies => crowAssemblies;
+ public string SelectedCrowAssembly {
+ get => selectedCrowAssembly;
+ set {
+ if (value == selectedCrowAssembly)
+ return;
+ selectedCrowAssembly = value;
+ CMDOptions_RemoveCrowAssembly.CanExecute = !string.IsNullOrEmpty(selectedCrowAssembly);
+ NotifyValueChanged(selectedCrowAssembly);
+ }
+ }
void saveCrowAssemblies () {
if (crowAssemblies.Count > 0)
Configuration.Global.Set ("CrowAssemblies", crowAssemblies.Aggregate ((a, b)=> $"{a};{b}"));
if (!Configuration.Global.TryGet<string> ("CrowAssemblies", out string assemblies))
return;
foreach (string a in assemblies.Split (';'))
- crowAssemblies.Add (a);
+ if (!string.IsNullOrEmpty(a))
+ crowAssemblies.Add (a);
}
-
+ #endregion
#region Mouse & Keyboard
Point mouseScreenPos;//absolute on screen position.
}
catch (System.Exception ex)
{
- Log(LogType.Error, $"[Error][DebugIFace mouse move]{ex}");
+ //Log(LogType.Error, $"[Error][DebugIFace mouse move]{ex}");
+ Debug.WriteLine(ex.Message);
+ Debug.WriteLine(ex.StackTrace);
}
}
}
using Crow;
using Drawing2D;
using IML = Crow.IML;
+using System.Diagnostics;
+using Crow.IML;
+using System.Runtime.Loader;
namespace CECrowPlugin
{
public override void Run()
{
initBackend ();
- Init();
+ try {
+ Init();
+ } catch (Exception e) {
+ Debug.WriteLine(e.Message);
+ Debug.WriteLine(e.StackTrace);
+ }
+
Thread t = new Thread (interfaceThread) {
IsBackground = true
};
t.Start ();
}
public bool Terminate;
- string source;
- Action delRegisterForRepaint;//call RegisterForRepaint in the container widget (DebugInterfaceWidget)
- Action<Exception> delCrowServiceSetCurrentException;
-
- delegate void GetScreenCoordinateDelegateType(out int x, out int y);
- GetScreenCoordinateDelegateType delCrowServiceGetScreenCoordinate;
- Func<IEnumerable<object>> delCrowServiceGetStyling;
- Func<string, Stream> delCrowServiceGetStreamFromPath;
-
void interfaceThread () {
while (!Terminate) {
try
}
/*if (IsDirty)
- delRegisterForRepaint(); */
+ delRegisterForRepaint();*/
Thread.Sleep (UPDATE_INTERVAL);
}
Dispose();
}
+ string source;
+ //Action delRegisterForRepaint;//call RegisterForRepaint in the container widget (DebugInterfaceWidget)
+ Action<Exception> delCrowServiceSetCurrentException;
+
+ delegate void GetScreenCoordinateDelegateType(out int x, out int y);
+ GetScreenCoordinateDelegateType delCrowServiceGetScreenCoordinate;
+ Func<IEnumerable<object>> delCrowServiceGetStyling;
+ Func<string, Stream> delCrowServiceGetStreamFromPath;
+
+
public void RegisterDebugInterfaceCallback (object crowService){
Type t = crowService.GetType();
//delRegisterForRepaint = (Action)Delegate.CreateDelegate(typeof(Action), w, t.GetMethod("RegisterForRepaint"));
}
}
}
+
void resetInterface () {
ClearInterface();
initDictionaries();
public void Resize (int width, int height) {
ProcessResize (new Rectangle(0, 0, width, height));
}
- /*public override void ProcessResize(Rectangle bounds) {
+ /*public override void ProcessResize(Rectangle bounds) {
lock (UpdateMutex) {
clientRectangle = bounds.Size;
RegisterClip (clientRectangle);
}
}*/
- public override void ForceMousePosition()
+ public override Widget HoverWidget {
+ get => base.HoverWidget;
+ set {
+ base.HoverWidget = value;
+ }
+ }
+ public override bool OnMouseMove(int x, int y)
+ {
+ return base.OnMouseMove(x, y);
+ }
+
+ public override void ForceMousePosition()
{
delCrowServiceGetScreenCoordinate(out int x, out int y);
Glfw.Glfw3.SetCursorPosition (WindowHandle, x, y);
public override Type GetWidgetTypeFromName (string typeName){
if (knownCrowWidgetTypes.ContainsKey (typeName))
return knownCrowWidgetTypes [typeName];
- System.Runtime.Loader.AssemblyLoadContext dbgLoadCtx =
- System.Runtime.Loader.AssemblyLoadContext.All.FirstOrDefault (ctx=>ctx.Name == "CrowDebuggerLoadContext");
+ AssemblyLoadContext dbgLoadCtx =
+ AssemblyLoadContext.All.FirstOrDefault (ctx=>ctx.Name == "CrowDebuggerLoadContext");
foreach (Assembly a in dbgLoadCtx.Assemblies) {
try {
foreach (Type expT in a.GetExportedTypes ()) {
}
return null;
}
+ public override MethodInfo SearchExtMethod (Type t, string methodName) {
+ string key = t.Name + "." + methodName;
+ if (knownExtMethods.ContainsKey (key))
+ return knownExtMethods [key];
+
+ Debug.WriteLine ($"[CECrowPlugin] search extension method: {t};{methodName} => key={key}");
+
+ MethodInfo mi = null;
+ AssemblyLoadContext dbgLoadCtx =
+ AssemblyLoadContext.All.FirstOrDefault (ctx=>ctx.Name == "CrowDebuggerLoadContext");
+ foreach (Assembly a in dbgLoadCtx.Assemblies) {
+ try {
+ if (CompilerServices.TryGetExtensionMethods (a, t, methodName, out mi)) {
+ break;
+ }
+ } catch (Exception ex) {
+ Console.WriteLine ($"[CECrowPlugin]Error: SearchExtMethod failed for {t};{methodName} => key={key}");
+ }
+ }
+
+ if (mi == null) {
+ Debug.WriteLine ($"[CECrowPlugin] Extension method not found: {t};{methodName} => key={key}");
+ return null;
+ }
+
+ knownExtMethods.Add (key, mi);
+ return mi;
+ }
+ public Type GetTypeFromName (string typeName) {
+ AssemblyLoadContext dbgLoadCtx =
+ AssemblyLoadContext.All.FirstOrDefault (ctx=>ctx.Name == "CrowDebuggerLoadContext");
+ foreach (Assembly a in dbgLoadCtx.Assemblies) {
+ try {
+ foreach (Type expT in a.GetExportedTypes ()) {
+ if (string.Equals(expT.Name,typeName,StringComparison.Ordinal))
+ return expT;
+ }
+ } catch (Exception ex) {
+ Console.WriteLine ($"[CECrowPlugin]Error: GetWidgetTypeFromName failed for {typeName} in {a}.\n{ex}");
+ }
+ }
+ return null;
+ }
+
+
+ public void LockRenderMutex() => Monitor.Enter(this.UpdateMutex);
+ public void UnlockRenderMutex() => Monitor.Exit(this.UpdateMutex);
}
}
\ No newline at end of file
new Command("Load from file", () => loadLogFromDebugLogFilePath ())
);*/
public CommandGroup WindowCommands => new CommandGroup (
- CMDRefresh, CMDZoomIn, CMDZoomOut,
+ CMDRefresh, //CMDZoomIn, CMDZoomOut,
crowIFaceService.CMDStartRecording,
crowIFaceService.CMDStopRecording,
crowIFaceService.CMDOpenConfig,
public override bool Paint(IContext ctx)
{
- return base.Paint(ctx);
+ crowIFaceService.LockRenderMutex();
+ try {
+ return base.Paint(ctx);
+ } finally {
+ crowIFaceService.UnlockRenderMutex();
+ }
}
protected override void RecreateCache()
{
- //bmp?.Dispose ();
-
if (crowIFaceService != null && crowIFaceService.IsRunning) {
- crowIFaceService.Resize (Slot.Width, Slot.Height);
bmp = crowIFaceService.MainSurface;
} else
base.RecreateCache ();
}
protected override void UpdateCache(IContext ctx)
{
- if (bmp != null) {
+ if (crowIFaceService != null && crowIFaceService.IsRunning && bmp != null) {
+ crowIFaceService.LockRenderMutex();
paintCache (ctx, Slot + Parent.ClientRectangle.Position);
- crowIFaceService?.ResetDirtyState ();
+ crowIFaceService.UnlockRenderMutex();
+ crowIFaceService.ResetDirtyState ();
+ }
+
+ }
+ public override void OnLayoutChanges (LayoutingType layoutType)
+ {
+ base.OnLayoutChanges (layoutType);
+ switch (layoutType) {
+ case LayoutingType.Width:
+ //DesignWidth = Slot.Width * 100 / zoom;
+ crowIFaceService.Resize (Slot.Width, Slot.Height);
+ break;
+ case LayoutingType.Height:
+ //DesignHeight = Slot.Height * 100 / zoom;
+ crowIFaceService.Resize (Slot.Width, Slot.Height);
+ break;
}
}
-
protected override void Dispose(bool disposing)
{
CMDRefresh?.Dispose ();
- crowIFaceService?.Stop ();
+ //crowIFaceService?.Stop ();
base.Dispose(disposing);
}
}
using CrowEdit.Xml;
using Drawing2D;
+using System.Diagnostics;
namespace CECrowPlugin
{
IEnumerable<MemberInfo> getAllCrowTypeMembers (string crowTypeName) {
- Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName);
+ Type crowType = App.GetService<CrowService>()?.GetWidgetTypeFromeName(crowTypeName);
return crowType?.GetMembers (BindingFlags.Public | BindingFlags.Instance).
Where (m=>((m is PropertyInfo pi && pi.CanWrite) || (m is EventInfo)) &&
m.GetCustomAttribute<XmlIgnoreAttribute>() == null);
}
- MemberInfo getCrowTypeMember (string crowTypeName, string memberName) {
- Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName);
+ /*MemberInfo getCrowTypeMember (string crowTypeName, string memberName) {
+ Type crowType = App.GetService<CrowService>()?.GetWidgetTypeFromeName(crowTypeName);
return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
- }
+ }*/
protected override IEnumerable<Suggestion> getElementNameSuggestions(string curName, TextChange change)
{
- IEnumerable<Type> widgetTypes = typeof (Widget).Assembly.GetExportedTypes ().Where(t=>
- typeof(Widget).IsAssignableFrom (t) && !t.IsAbstract);
+ CrowService srv = App.GetService<CrowService>();
+ if (srv == null || !srv.IsRunning)
+ return null;
+ Type widgetType = srv.GetWidgetTypeFromeName("Widget");
+ if (widgetType == null)
+ return null;
+
+ IEnumerable<Type> widgetTypes = widgetType.Assembly.GetExportedTypes ().Where(t=>
+ widgetType.IsAssignableFrom (t) && !t.IsAbstract);
int curNameLength = 0;
if (!string.IsNullOrEmpty(curName)) {
widgetTypes = widgetTypes.Where(t=>t.Name.StartsWith(curName, StringComparison.OrdinalIgnoreCase));
protected override IEnumerable<Suggestion> getAttributeNameSuggestions(string eltName, string curName, TextChange change) {
int endPosOffset = change.HasNewText ? -1 : 0;
var members = getAllCrowTypeMembers(eltName);
+ if (members == null)
+ return null;
if (!string.IsNullOrEmpty(curName))
members = members.Where(m =>
- m.Name.StartsWith (curName, StringComparison.OrdinalIgnoreCase));
- return members.Select(m
+ m.Name.StartsWith (curName, StringComparison.OrdinalIgnoreCase));
+ return members?.Select(m
=> new MemberInfoSuggestion(m,
new TextChange(change.Start, change.Length, m.Name + change.ChangedText), endPosOffset));
}
protected override IEnumerable<Suggestion> getAttributeValueSuggestions(string eltName, string attribName, string attribValue, TextChange change) {
- MemberInfo mi = getAllCrowTypeMembers(eltName).Where(m=>m.Name.Equals(attribName, StringComparison.Ordinal)).FirstOrDefault();
+ CrowService srv = App.GetService<CrowService>();
+ if (srv == null || !srv.IsRunning)
+ return null;
+ MemberInfo mi = getAllCrowTypeMembers(eltName)?.Where(m=>m.Name.Equals(attribName, StringComparison.Ordinal)).FirstOrDefault();
if (mi is PropertyInfo pi) {
if (pi.Name == "Style")
return App.Styling.Keys
Where (s => s.StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(s=>new Suggestion(s,
new TextChange(change.Start, change.Length, s + change.ChangedText)));
- if (pi.PropertyType == typeof (Measure))
+ if (pi.PropertyType.Name == "Measure")
return (new string[] {"Stretched", "Fit"}).
Where (s => s.StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(s=>new Suggestion(s,
new TextChange(change.Start, change.Length, s + change.ChangedText)));
- if (pi.PropertyType == typeof (Fill))
+ if (pi.PropertyType.Name == "Fill")
return EnumsNET.Enums.GetValues<Colors> ()
.Where (s => s.ToString().StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(c=>new ColorSuggestion(c,
Template = "#CECrowPlugin.ui.Button.template";
Background = "Onyx";
}
-CheckBox2 {
- Template= "#CECrowPlugin.ui.CheckBox2.imlt";
- Background = "Jet";
- Checked="{Background=MediumSeaGreen}";
- Unchecked = "{Background=Jet}";
- Width = "200";
-}
+
smallLabCaption {
Font="mono, 8";
Foreground="Grey";
<Label Fit="true" Text="Assembly Name:"/>
<Label Fit="true" Text="{CrowAssemblyName}"/>
</HorizontalStack>
+ <HorizontalStack Height="Fit" Spacing="5">
+ <CheckBox Style="StateBox" Caption="Design mode is enabled" IsChecked="{DesignModeEnabled}"/>
+ <CheckBox Style="StateBox" Caption="Debug logger is enabled" IsChecked="{DebugLogIsEnabled}"/>
+ </HorizontalStack>
</VerticalStack>
</GroupBox>
<Label Background="Red" Foreground="White" Margin="5" Width="Stretched" Text="{ServiceErrorMessage}"
IsVisible="{ServiceIsInError}"/>
- <ListBox Style="ScrollingListBox" Data="{CrowAssemblies}" MinimumSize="100,200"/>
+ <ListBox Style="ScrollingListBox" Data="{CrowAssemblies}" MinimumSize="100,200" SelectedItem="{²SelectedCrowAssembly}"/>
<HorizontalStack Height="Fit" Width="Fit" HorizontalAlignment="Right">
<Button Command="{CMDOptions_AddCrowAssembly}"/>
+ <Button Command="{CMDOptions_RemoveCrowAssembly}"/>
</HorizontalStack>
<Spinner Caption="Zoom Factor" Value="{²ZoomFactor}" Minimum="0.2" Maximum="4.0" SmallIncrement="0.1" LargeIncrement="0.2"/>
<Spinner Caption="Refresh Rate (ms)" Value="{²RefreshRate}" Maximum="1000"/>
eltStart.name.HasValue) {
if (prevTok.Is(XmlTokenType.AttributeName)) {
- TextChange change = new TextChange(prevTok.Start, prevTok.End);
+ TextChange change = new TextChange(prevTok.Start, prevTok.Length);
if (!tok.Is(XmlTokenType.EqualSign))
change.ChangedText += "=\"\"";
return getAttributeNameSuggestions(eltStart.Name, attrib.Name, change).ToList();
<?xml version="1.0"?>
-<DockWindow Caption="Syntax" Width="40%">
+<DockWindow Caption="Syntax" Width="30%">
<VerticalStack RootDataLevel="true" Spacing="0" DataSource="{CurrentDocument}">
<Button Command="{CMDRefreshSyntaxTree}"/>
<Label Text="{}"/>