summaryrefslogtreecommitdiff
path: root/Source/ModelViewer/Main.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ModelViewer/Main.cs')
-rw-r--r--Source/ModelViewer/Main.cs1740
1 files changed, 870 insertions, 870 deletions
diff --git a/Source/ModelViewer/Main.cs b/Source/ModelViewer/Main.cs
index 5fed89da..4697e454 100644
--- a/Source/ModelViewer/Main.cs
+++ b/Source/ModelViewer/Main.cs
@@ -1,870 +1,870 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-
-using System.IO;
-using Microsoft.Boogie;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie.ModelViewer
-{
- public partial class Main : Form
- {
- SkeletonItem unfoldingRoot;
- SkeletonItem[] allItems;
- public int CurrentState, PreviousState = -1;
- IState[] states;
- internal ILanguageProvider langProvider;
- public ILanguageSpecificModel LangModel;
- ToolStripMenuItem[] viewItems;
- Model currentModel;
- Model[] allModels;
- int modelId;
- string lastModelFileName;
- internal ViewOptions viewOpts = new ViewOptions();
- Font smallFont, largeFont;
- int lineHeight;
-
- // TODO this should be dynamically loaded
- IEnumerable<ILanguageProvider> Providers()
- {
- yield return BCT.Provider.Instance;
- yield return Vcc.Provider.Instance;
- yield return Dafny.Provider.Instance;
- yield return Base.Provider.Instance;
- }
-
- public Main(string[] args, bool runAsHostedWindow = false)
- {
- InitializeComponent();
-
- smallFont = stateList.Font;
-
- if (runAsHostedWindow) {
- this.fileToolStripMenuItem.Enabled = false;
- this.fileToolStripMenuItem.Visible = false;
- }
-
- viewItems = new ToolStripMenuItem[] {
- normalToolStripMenuItem,
- expertToolStripMenuItem,
- everythingToolStripMenuItem,
- includeTheKitchenSinkToolStripMenuItem
- };
-
- var debugBreak = false;
- string filename = null;
-
- for (int i = 1; i < args.Length; i++) {
- var arg = args[i];
- if (arg == "/break" || arg == "-break")
- debugBreak = true;
- else
- filename = arg;
- }
-
- if (debugBreak) {
- System.Diagnostics.Debugger.Launch();
- }
-
- if (filename != null) {
- var idx = filename.IndexOf(':');
- if (idx > 0) {
- modelId = int.Parse(filename.Substring(idx + 1));
- filename = filename.Substring(0, idx);
- }
- }
-
- this.ReadModels(filename, this.modelId);
- }
-
- private void SetWindowTitle(string fileName)
- {
- if (fileName == null) {
- this.Text = "Boogie Verification Debugger";
- } else {
- this.Text = Path.GetFileName(fileName) + " - Boogie Verification Debugger";
- }
- }
-
- public void ReadModel(string model, int setModelIdTo = 0)
- {
- Contract.Requires(model != null);
-
- using (var rd = new StringReader(model))
- {
- allModels = Model.ParseModels(rd).ToArray();
- }
-
- AddAndLoadModel(setModelIdTo);
- }
-
- public void ReadModels(string modelFileName, int setModelIdTo)
- {
- this.lastModelFileName = modelFileName;
- this.langProvider = Base.Provider.Instance;
-
- if (!string.IsNullOrWhiteSpace(modelFileName) && File.Exists(modelFileName)) {
- using (var rd = File.OpenText(modelFileName)) {
- allModels = Model.ParseModels(rd).ToArray();
- }
-
- AddAndLoadModel(setModelIdTo);
- } else {
- currentModel = new Model();
- }
-
- this.SetWindowTitle(modelFileName);
- }
-
- private void AddAndLoadModel(int setModelIdTo)
- {
- modelId = setModelIdTo;
-
- if (modelId >= allModels.Length)
- modelId = 0;
-
- currentModel = allModels[modelId];
- AddModelMenu();
-
- foreach (var p in Providers())
- {
- if (p.IsMyModel(currentModel))
- {
- this.langProvider = p;
- break;
- }
- }
-
- LoadModel(modelId);
- }
-
- private void LoadModel(int idx)
- {
- var i = 0;
-
- //var stateIdx = stateList.SelectedIndices.Count == 0 ? 0 : stateList.SelectedIndices[0];
-
- modelId = idx;
- foreach (ToolStripMenuItem it in modelsToolStripMenuItem.DropDownItems) {
- it.Checked = i++ == idx;
- }
- currentModel = allModels[idx];
- BuildModel();
-
- /*
- if (stateList.Items.Count <= stateIdx)
- stateIdx = 0;
- stateList.Items[stateIdx].Selected = true;
- */
- }
-
- private void AddModelMenu()
- {
- modelsToolStripMenuItem.DropDownItems.Clear();
- var idx = 0;
- foreach (var m in allModels) {
- var currIdx = idx++; // this local needs to be in this block
- var menuItem = modelsToolStripMenuItem.DropDownItems.Add(string.Format("Model #&{0}", currIdx), null, (s, a) => LoadModel(currIdx)) as ToolStripMenuItem;
- if (currIdx <= 9) {
- menuItem.ShortcutKeys = Keys.Control | (Keys)(currIdx + Keys.D0);
- }
- }
- }
-
- private void BuildModel()
- {
- stateList.Items.Clear();
-
- var items = new List<ListViewItem>();
- LangModel = langProvider.GetLanguageSpecificModel(currentModel, viewOpts);
- states = LangModel.States.ToArray();
- var oldRoot = unfoldingRoot;
- SkeletonItem selectedSkel = null;
- if (oldRoot != null && SelectedNode() != null) {
- selectedSkel = SelectedNode().skel;
- }
- unfoldingRoot = new SkeletonItem(this, states.Length);
- allItems = unfoldingRoot.PopulateRoot(states);
-
- var idx = 0;
- foreach (var i in states) {
- var it = new ListViewItem(new string[] { idx.ToString(), i.Name, "" });
- it.Tag = i;
- items.Add(it);
- idx++;
- }
- stateList.Items.AddRange(items.ToArray());
- unfoldingRoot.Expanded = true;
-
- if (oldRoot == null) {
- SetState(0);
- stateList.Items[0].Selected = true;
- SetColumnSizes();
- } else {
- var mapping = new Dictionary<SkeletonItem, SkeletonItem>();
- unfoldingRoot.SyncWith(mapping, oldRoot);
- SkeletonItem newIt = null;
- while (selectedSkel != null) {
- if (mapping.TryGetValue(selectedSkel, out newIt)) break;
- selectedSkel = selectedSkel.parent;
- }
- if (CurrentState >= stateList.Items.Count)
- CurrentState = 0;
- if (PreviousState >= stateList.Items.Count)
- PreviousState = -1;
- if (newIt != null) GotoNode(newIt);
- SyncStateListValues();
- UpdateMatches(true);
- }
- }
-
- private void SetColumnSizes()
- {
- currentStateView.Columns[0].Width = currentStateView.Width - currentStateView.Columns[1].Width - currentStateView.Columns[2].Width - 25;
- stateList.Columns[1].Width = stateList.Width - stateList.Columns[0].Width - stateList.Columns[2].Width - 25;
- }
-
- public void SetState(int id, bool updateView = false)
- {
- if (updateView)
- {
- stateList.SelectedIndices.Clear();
- stateList.SelectedIndices.Add(id);
- }
- if (CurrentState != id) {
- PreviousState = CurrentState;
- CurrentState = id;
- }
- UpdateMatches(true);
- }
-
- public void HideStateList()
- {
- stateList.Hide();
- splitContainer1.Panel2.Hide();
- splitContainer1.Panel2Collapsed = true;
- splitContainer1.SplitterDistance = splitContainer1.Width;
- }
-
- public void HideMenuStrip()
- {
- menuStrip1.Hide();
- }
-
- internal void Activate(TreeNode treeNode)
- {
- throw new NotImplementedException();
- }
-
- private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
- {
-
- }
-
- static Color Col(int c)
- {
- return Color.FromArgb(c >> 16, (c >> 8) & 0xff, c & 0xff);
- }
-
- static StringFormat center = new StringFormat() { Alignment = StringAlignment.Center };
- static Pen plusPen = new Pen(Col(0xaaaaaa));
- static Brush grayedOut = new SolidBrush(Col(0xaaaaaa));
- static Brush nonPrimary = new SolidBrush(Col(0xeeeeee));
- static Brush matchBg = new SolidBrush(Col(0xFFFA6F));
-
- static SolidBrush currentStateBrush = new SolidBrush(Color.Red);
- static SolidBrush regularStateBrush = new SolidBrush(Color.Black);
- static SolidBrush previousStateBrush = new SolidBrush(Color.Blue);
-
- static SolidBrush[] categoryBrushes = new SolidBrush[] {
- new SolidBrush(Color.Black), // Local
- new SolidBrush(Color.Black), // PhysField
- new SolidBrush(Color.Green), // SpecField
- new SolidBrush(Color.Peru), // MethodologyProperty
- new SolidBrush(Color.Green), // UserFunction
- new SolidBrush(Color.Black), // Maplet
- };
-
- private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
- {
- var item = (DisplayItem)e.Item;
- var skel = item.skel;
- var rect = e.Bounds;
- var listView = (ListView)sender;
- lineHeight = rect.Height;
- rect.Y += 1;
- rect.Height -= 2;
-
- var textBrush = Brushes.Black;
- if (listView.SelectedIndices.Count > 0 && listView.SelectedIndices[0] == e.ItemIndex) {
- e.Graphics.FillRectangle(Brushes.Aquamarine, rect);
- textBrush = Brushes.White;
- } else {
- var bg = Brushes.White;
- if (item.active && !skel.isPrimary[CurrentState])
- bg = nonPrimary;
- if (item.skel.isMatch)
- bg = matchBg;
- e.Graphics.FillRectangle(bg, rect);
- }
-
- var off = lineHeight * item.skel.level;
- if (item.IsMatchListItem)
- off = 0;
-
- {
- var plusRect = rect;
- plusRect.Width = lineHeight;
- plusRect.X += off;
- var plusBorder = plusRect;
- plusBorder.Height = lineHeight / 2;
- plusBorder.Width = lineHeight / 2;
- plusBorder.X += lineHeight / 4;
- plusBorder.Y += lineHeight / 4;
- e.Graphics.DrawRectangle(plusPen, plusBorder);
- if (skel.Expandable) {
- float midX = plusBorder.X + plusBorder.Width / 2;
- float midY = plusBorder.Y + plusBorder.Height / 2;
- e.Graphics.DrawLine(plusPen, plusBorder.X + 2, midY, plusBorder.Right - 2, midY);
- if (!item.skel.expanded)
- e.Graphics.DrawLine(plusPen, midX, plusBorder.Y + 2, midX, plusBorder.Bottom - 2);
- }
- }
-
- off += lineHeight + 3;
- var nameRect = rect;
- var font = listView.Font;
-
- textBrush = categoryBrushes[(int)item.dispNode.Category];
-
- if (!item.active)
- textBrush = grayedOut;
-
- nameRect.Width = listView.Columns[0].Width - 1 - off;
- nameRect.X += off;
- var width = DrawString(e.Graphics, item.SubItems[0].Text, font, textBrush, nameRect);
-
- textBrush = item.active ? Brushes.Black : grayedOut;
- nameRect.X += width + 4;
- nameRect.Width = listView.Columns[0].Width + listView.Columns[1].Width - nameRect.X;
- width = DrawString(e.Graphics, item.SubItems[1].Text, font, textBrush, nameRect);
-
- nameRect.X += width + 4;
- nameRect.Width = listView.Width - nameRect.X;
- var t = item.SubItems[2].Text;
- width = DrawString(e.Graphics, t, font, t == item.SubItems[1].Text ? grayedOut : Brushes.Black, nameRect);
- }
-
- private int DrawString(Graphics g, string s, Font font, Brush textBrush, Rectangle minRect)
- {
- var sz = g.MeasureString(s, font).Width;
- if (sz > minRect.Width - 2) {
- minRect.Width = (int)(sz + 20);
- }
- g.DrawString(s, font, textBrush, minRect);
- return minRect.Width;
- }
-
- private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
- {
- e.DrawBackground();
- var brush = regularStateBrush;
- if (e.Header.Index == 1)
- brush = currentStateBrush;
- else if (e.Header.Index == 2)
- brush = previousStateBrush;
-
- Rectangle r = e.Bounds;
- r.X += 5;
- r.Y += 4;
- DrawString(e.Graphics, e.Header.Text, e.Header.ListView.Font, brush, r);
- }
-
- private void listView1_MouseUp(object sender, MouseEventArgs e)
- {
- var clickedItem = (DisplayItem)currentStateView.GetItemAt(5, e.Y);
- if (clickedItem != null) {
- clickedItem.Selected = true;
- clickedItem.Focused = true;
-
- var skel = clickedItem.skel;
- int plusLoc = skel.level * lineHeight;
- if (skel.Expandable && e.X >= plusLoc && e.X <= plusLoc + lineHeight) {
- skel.Expanded = !skel.Expanded;
- SyncCurrentStateView();
- }
- }
- }
-
- private void SyncCurrentStateView()
- {
- SyncListView(unfoldingRoot.RecChildren, currentStateView, (x, y) => { });
- }
-
- private void SyncListView(IEnumerable<SkeletonItem> items, ListView listView, Action<DisplayItem, SkeletonItem> cb)
- {
- var ch = items.ToArray();
- var missing = ch.Length - listView.Items.Count;
- listView.BeginUpdate();
- if (missing < 0) {
- missing = -missing;
- while (missing-- > 0) {
- listView.Items.RemoveAt(listView.Items.Count - 1);
- }
- } else {
- while (missing-- > 0) {
- listView.Items.Add(new DisplayItem());
- }
- }
- for (int i = 0; i < ch.Length; ++i) {
- var di = (DisplayItem)listView.Items[i];
- cb(di, ch[i]);
- di.Set(ch[i], CurrentState, PreviousState);
- }
- listView.EndUpdate();
- listView.Invalidate();
- }
-
- private void listView1_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
- {
- currentStateView.Invalidate();
- }
-
- private void listView1_Resize(object sender, EventArgs e)
- {
- SetColumnSizes();
- currentStateView.Invalidate();
- }
-
- private void stateList_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (stateList.SelectedItems.Count == 0) return;
- var sel = stateList.SelectedItems[0].Index;
-
- if (PreviousState >= 0)
- stateList.Items[PreviousState].ForeColor = regularStateBrush.Color;
-
- SetState(sel);
- }
-
- DisplayItem SelectedNode()
- {
- if (currentStateView.SelectedItems.Count == 0) return null;
- return (DisplayItem)currentStateView.SelectedItems[0];
- }
-
- private void currentStateView_SelectedIndexChanged(object sender, EventArgs e)
- {
- SyncStateListValues();
- }
-
- private void SyncStateListValues()
- {
- var sel = SelectedNode();
- if (sel == null) return;
-
- stateList.BeginUpdate();
- for (int i = 0; i < sel.skel.displayNodes.Length; ++i) {
- var dn = sel.skel.displayNodes[i];
- stateList.Items[i].SubItems[2].Text = dn == null ? "" : dn.Value;
- }
- stateList.EndUpdate();
- }
-
- private void ExpandParents(SkeletonItem item)
- {
- item = item.parent;
- while (item != null) {
- item.Expanded = true;
- item = item.parent;
- }
- }
-
- private void textBox1_TextChanged(object sender, EventArgs e)
- {
- UpdateMatches(false);
- }
-
- private void UpdateMatches(bool force)
- {
- var bad = false;
- Model.Element eltEq = null;
- var eltRef = new List<Model.Element>();
- var words = new List<string>();
-
- foreach (var w in textBox1.Text.Split(' ')) {
- if (w == "") continue;
- if (w.StartsWith("eq:")) {
- if (eltEq != null) bad = true;
- else {
- eltEq = LangModel.FindElement(w.Substring(3));
- if (eltEq == null) bad = true;
- }
- } else if (w.StartsWith("use:")) {
- var e = LangModel.FindElement(w.Substring(4));
- if (e == null) bad = true;
- else eltRef.Add(e);
- } else {
- words.Add(w.ToLower());
- }
- }
-
- textBox1.ForeColor = bad ? Color.Red : Color.Black;
-
- var wordsA = words.ToArray();
- var refsA = eltRef.ToArray();
-
- if (eltEq == null && wordsA.Length == 0 && refsA.Length == 0)
- bad = true;
-
- var changed = true; // force;
- var matches = new List<SkeletonItem>();
-
- foreach (var s in allItems) {
- var newMatch = false;
- if (s.isPrimary[CurrentState] && !bad) {
- newMatch = s.MatchesWords(wordsA, refsA, eltEq, CurrentState);
- }
- if (newMatch)
- matches.Add(s);
- if (s.isMatch != newMatch) {
- changed = true;
- s.isMatch = newMatch;
- }
- }
-
- if (PreviousState >= 0)
- stateList.Items[PreviousState].ForeColor = previousStateBrush.Color;
- stateList.Items[CurrentState].ForeColor = currentStateBrush.Color;
-
- if (changed) {
- SyncListView(matches, matchesList, (di, _) => { di.IsMatchListItem = true; });
- SyncCurrentStateView();
- }
- }
-
- private void matchesList_Resize(object sender, EventArgs e)
- {
- matchesList.Invalidate();
- }
-
- private void matchesList_DoubleClick(object sender, EventArgs e)
- {
- if (matchesList.SelectedItems.Count == 0) return;
- var sel = (DisplayItem)matchesList.SelectedItems[0];
- GotoNode(sel.skel);
- }
-
- private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
- {
- foreach (DisplayItem it in matchesList.Items) {
- ExpandParents(it.skel);
- }
- SyncCurrentStateView();
- }
-
- private void SetSearch(string text)
- {
- textBox1.Text = text;
- }
-
- private void GotoNode(SkeletonItem skel)
- {
- ExpandParents(skel);
- SyncCurrentStateView();
- foreach (DisplayItem it in currentStateView.Items) {
- if (it.skel == skel) {
- it.Selected = true;
- currentStateView.EnsureVisible(it.Index);
- break;
- }
- }
- }
-
- private IEnumerable<SkeletonItem> NamesFor(Model.Element elt)
- {
- var words = new string[0];
- var elts = new Model.Element[0];
-
- foreach (var s in allItems) {
- if (s.isPrimary[CurrentState] && s.MatchesWords(words, elts, elt, CurrentState)) {
- yield return s;
- }
- }
- }
-
- private void AddMenuItems(IEnumerable<SkeletonItem> skels, ToolStripItemCollection items, string pref, int max)
- {
- var skelsM = skels.Take(max).ToArray();
-
- foreach (var s in skelsM) {
- var tmp = s;
- items.Add(pref + s.LongName(CurrentState), null, (x, _) => GotoNode(tmp));
- }
-
- if (skelsM.Length == max)
- items.Add(new ToolStripMenuItem("...") { Enabled = false });
- }
-
- private void stateViewMenu_Opening(object sender, CancelEventArgs e)
- {
- IDisplayNode sel = null;
- SkeletonItem skel = null;
- if (SelectedNode() != null) {
- sel = SelectedNode().dispNode;
- skel = SelectedNode().skel;
- }
-
- var items = stateViewMenu.Items;
- items.Clear();
-
- if (sel == null) {
- items.Add(new ToolStripMenuItem("Unavailable") { Enabled = false });
- return;
- }
-
- foreach (var x in sel.References.Where(q => q != sel.Element)) {
- var t = new ToolStripMenuItem(LangModel.CanonicalName(x));
- items.Add(t);
- AddMenuItems(NamesFor(x), t.DropDownItems, "= ", 20);
- }
-
- if (sel.Element != null) {
- var selName = LangModel.CanonicalName(sel.Element);
- items.Add("Find uses...", null, (s, _) => SetSearch("use:" + selName));
-
- var aliases = NamesFor(sel.Element).Where(s => s != skel).ToArray();
- if (aliases.Length > 0) {
- items.Add("Aliases...", null, (s, _) => SetSearch("eq:" + selName));
- AddMenuItems(aliases, items, " = ", 10);
- }
- }
- }
-
- private void normalToolStripMenuItem_Click(object sender, EventArgs e)
- {
- int viewLev = -1;
- for (int i = 0; i < viewItems.Length; ++i) {
- if (viewItems[i] == sender) {
- viewLev = i;
- viewItems[i].Checked = true;
- } else {
- viewItems[i].Checked = false;
- }
- }
- if (viewLev != -1 && viewLev != viewOpts.ViewLevel) {
- viewOpts.ViewLevel = viewLev;
- BuildModel();
- }
- }
-
- private void debugToolStripMenuItem_Click(object sender, EventArgs e)
- {
- debugToolStripMenuItem.Checked = !debugToolStripMenuItem.Checked;
- viewOpts.DebugMode = debugToolStripMenuItem.Checked;
- BuildModel();
- }
-
- private void exitToolStripMenuItem_Click(object sender, EventArgs e)
- {
- this.Close();
- }
-
- private void reloadModelFileToolStripMenuItem_Click(object sender, EventArgs e)
- {
- ReadModels(this.lastModelFileName, this.modelId);
- }
-
- private SourceView sourceView;
- private void ShowSource()
- {
- if (stateList.SelectedItems.Count == 0) return;
- var li = stateList.SelectedItems[0] as ListViewItem;
- if (li != null) {
- var r = ((IState)li.Tag).ShowSource();
- if (r != null) {
- if (sourceView == null) {
- sourceView = new SourceView();
- }
- sourceView.largeFont = largeFontToolStripMenuItem.Checked;
- sourceView.SetSourceLocation(r);
- sourceView.BringToFront();
- }
- }
- }
-
- private void showSourceToolStripMenuItem_Click(object sender, EventArgs e)
- {
- ShowSource();
- }
-
- private void stateList_DoubleClick(object sender, EventArgs e)
- {
- ShowSource();
- }
-
- private void openModelMenuItem_Click(object sender, EventArgs e)
- {
- if (this.openModelFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
- this.ReadModels(this.openModelFileDialog.FileName, 0);
- }
- }
-
- private void largeFontToolStripMenuItem_Click(object sender, EventArgs e)
- {
- largeFontToolStripMenuItem.Checked = !largeFontToolStripMenuItem.Checked;
-
- if (largeFont == null) {
- largeFont = new Font(smallFont.FontFamily, smallFont.Size * 2, smallFont.Unit);
- }
-
- SetFont(largeFontToolStripMenuItem.Checked ? largeFont : smallFont);
- //textBox1.Font = font;
- //linkLabel1.Font = font;
- //label1.Font = font;
- }
-
- public void SetFont(System.Drawing.Font font)
- {
- stateList.Font = font;
- currentStateView.Font = font;
- matchesList.Font = font;
- }
-
- private void Main_Load(object sender, EventArgs e)
- {
-
- }
-
- private void currentStateView_KeyDown(object sender, KeyEventArgs e)
- {
- var node = SelectedNode();
- if (node == null) return;
-
- if (e.KeyCode == Keys.Right && !node.skel.Expanded && node.skel.Expandable) {
- node.skel.Expanded = true;
- SyncCurrentStateView();
- return;
- }
-
- if (e.KeyCode == Keys.Left) {
- if (node.skel.Expanded) {
- node.skel.Expanded = false;
- SyncCurrentStateView();
- return;
- } else {
- var par = node.skel.parent;
- if (par != null && par.parent != null) {
- // par.Expanded = false;
- foreach (DisplayItem it in currentStateView.Items) {
- it.Selected = it.skel == par;
- it.Focused = it.skel == par;
- if (it.Selected) {
- it.EnsureVisible();
- }
- }
- SyncCurrentStateView();
- }
- }
- }
- }
- }
-
- internal class DisplayItem : ListViewItem
- {
- internal SkeletonItem skel;
- internal int stateId;
- internal bool active;
- internal IDisplayNode dispNode;
-
- public bool IsMatchListItem { get; set; }
-
- internal void Set(SkeletonItem s, int id, int prevId)
- {
- if (skel == s && stateId == id)
- return;
- skel = s;
- stateId = id;
-
- dispNode = skel.displayNodes[stateId];
- active = dispNode != null;
-
- var closeStateId = stateId;
-
- if (dispNode == null) {
- while (closeStateId < skel.displayNodes.Length && skel.displayNodes[closeStateId] == null)
- closeStateId++;
- if (closeStateId >= skel.displayNodes.Length) {
- closeStateId = stateId;
- while (closeStateId >= 0 && skel.displayNodes[closeStateId] == null)
- closeStateId--;
- }
- dispNode = skel.displayNodes[closeStateId];
- }
-
- var fullName = skel.LongName(closeStateId);
- var tooltip = dispNode.ToolTip;
- if (tooltip == null)
- tooltip = "";
- if(tooltip.Length > 0 && tooltip[tooltip.Length - 1] != '\n')
- tooltip += "\n";
- tooltip += "Full name: " + fullName;
- if (tooltip != null) {
- this.ToolTipText = tooltip;
- }
-
- var name = dispNode.Name;
- if (name != dispNode.ShortName)
- {
- name = dispNode.ShortName;
- }
-
- if (IsMatchListItem) {
- Util.Assert(active);
- name = fullName;
- }
-
- this.SubItems[0].Text = name;
- this.SubItems[1].Text = active ? dispNode.Value : "";
-
- var prev = "";
-
- if (!IsMatchListItem && prevId >= 0 && skel.displayNodes[prevId] != null) {
- prev = skel.displayNodes[prevId].Value;
- }
-
- this.SubItems[2].Text = prev;
- }
-
- internal DisplayItem()
- : base(new string[] { "", "", "" })
- {
- }
-
- /*
- static internal string AliasesAsString(IDisplayNode dn)
- {
- if (dn == null) return "";
-
- var sb = new StringBuilder();
- var canon = dn.CanonicalValue;
- foreach (var n in dn.Aliases) {
- if (n == canon)
- continue;
- sb.Append(n).Append(", ");
- if (sb.Length > 300)
- break;
- }
- if (sb.Length > 2) sb.Length -= 2;
- return sb.ToString();
- }
- */
- }
-}
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+using System.IO;
+using Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie.ModelViewer
+{
+ public partial class Main : Form
+ {
+ SkeletonItem unfoldingRoot;
+ SkeletonItem[] allItems;
+ public int CurrentState, PreviousState = -1;
+ IState[] states;
+ internal ILanguageProvider langProvider;
+ public ILanguageSpecificModel LangModel;
+ ToolStripMenuItem[] viewItems;
+ Model currentModel;
+ Model[] allModels;
+ int modelId;
+ string lastModelFileName;
+ internal ViewOptions viewOpts = new ViewOptions();
+ Font smallFont, largeFont;
+ int lineHeight;
+
+ // TODO this should be dynamically loaded
+ IEnumerable<ILanguageProvider> Providers()
+ {
+ yield return BCT.Provider.Instance;
+ yield return Vcc.Provider.Instance;
+ yield return Dafny.Provider.Instance;
+ yield return Base.Provider.Instance;
+ }
+
+ public Main(string[] args, bool runAsHostedWindow = false)
+ {
+ InitializeComponent();
+
+ smallFont = stateList.Font;
+
+ if (runAsHostedWindow) {
+ this.fileToolStripMenuItem.Enabled = false;
+ this.fileToolStripMenuItem.Visible = false;
+ }
+
+ viewItems = new ToolStripMenuItem[] {
+ normalToolStripMenuItem,
+ expertToolStripMenuItem,
+ everythingToolStripMenuItem,
+ includeTheKitchenSinkToolStripMenuItem
+ };
+
+ var debugBreak = false;
+ string filename = null;
+
+ for (int i = 1; i < args.Length; i++) {
+ var arg = args[i];
+ if (arg == "/break" || arg == "-break")
+ debugBreak = true;
+ else
+ filename = arg;
+ }
+
+ if (debugBreak) {
+ System.Diagnostics.Debugger.Launch();
+ }
+
+ if (filename != null) {
+ var idx = filename.IndexOf(':');
+ if (idx > 0) {
+ modelId = int.Parse(filename.Substring(idx + 1));
+ filename = filename.Substring(0, idx);
+ }
+ }
+
+ this.ReadModels(filename, this.modelId);
+ }
+
+ private void SetWindowTitle(string fileName)
+ {
+ if (fileName == null) {
+ this.Text = "Boogie Verification Debugger";
+ } else {
+ this.Text = Path.GetFileName(fileName) + " - Boogie Verification Debugger";
+ }
+ }
+
+ public void ReadModel(string model, int setModelIdTo = 0)
+ {
+ Contract.Requires(model != null);
+
+ using (var rd = new StringReader(model))
+ {
+ allModels = Model.ParseModels(rd).ToArray();
+ }
+
+ AddAndLoadModel(setModelIdTo);
+ }
+
+ public void ReadModels(string modelFileName, int setModelIdTo)
+ {
+ this.lastModelFileName = modelFileName;
+ this.langProvider = Base.Provider.Instance;
+
+ if (!string.IsNullOrWhiteSpace(modelFileName) && File.Exists(modelFileName)) {
+ using (var rd = File.OpenText(modelFileName)) {
+ allModels = Model.ParseModels(rd).ToArray();
+ }
+
+ AddAndLoadModel(setModelIdTo);
+ } else {
+ currentModel = new Model();
+ }
+
+ this.SetWindowTitle(modelFileName);
+ }
+
+ private void AddAndLoadModel(int setModelIdTo)
+ {
+ modelId = setModelIdTo;
+
+ if (modelId >= allModels.Length)
+ modelId = 0;
+
+ currentModel = allModels[modelId];
+ AddModelMenu();
+
+ foreach (var p in Providers())
+ {
+ if (p.IsMyModel(currentModel))
+ {
+ this.langProvider = p;
+ break;
+ }
+ }
+
+ LoadModel(modelId);
+ }
+
+ private void LoadModel(int idx)
+ {
+ var i = 0;
+
+ //var stateIdx = stateList.SelectedIndices.Count == 0 ? 0 : stateList.SelectedIndices[0];
+
+ modelId = idx;
+ foreach (ToolStripMenuItem it in modelsToolStripMenuItem.DropDownItems) {
+ it.Checked = i++ == idx;
+ }
+ currentModel = allModels[idx];
+ BuildModel();
+
+ /*
+ if (stateList.Items.Count <= stateIdx)
+ stateIdx = 0;
+ stateList.Items[stateIdx].Selected = true;
+ */
+ }
+
+ private void AddModelMenu()
+ {
+ modelsToolStripMenuItem.DropDownItems.Clear();
+ var idx = 0;
+ foreach (var m in allModels) {
+ var currIdx = idx++; // this local needs to be in this block
+ var menuItem = modelsToolStripMenuItem.DropDownItems.Add(string.Format("Model #&{0}", currIdx), null, (s, a) => LoadModel(currIdx)) as ToolStripMenuItem;
+ if (currIdx <= 9) {
+ menuItem.ShortcutKeys = Keys.Control | (Keys)(currIdx + Keys.D0);
+ }
+ }
+ }
+
+ private void BuildModel()
+ {
+ stateList.Items.Clear();
+
+ var items = new List<ListViewItem>();
+ LangModel = langProvider.GetLanguageSpecificModel(currentModel, viewOpts);
+ states = LangModel.States.ToArray();
+ var oldRoot = unfoldingRoot;
+ SkeletonItem selectedSkel = null;
+ if (oldRoot != null && SelectedNode() != null) {
+ selectedSkel = SelectedNode().skel;
+ }
+ unfoldingRoot = new SkeletonItem(this, states.Length);
+ allItems = unfoldingRoot.PopulateRoot(states);
+
+ var idx = 0;
+ foreach (var i in states) {
+ var it = new ListViewItem(new string[] { idx.ToString(), i.Name, "" });
+ it.Tag = i;
+ items.Add(it);
+ idx++;
+ }
+ stateList.Items.AddRange(items.ToArray());
+ unfoldingRoot.Expanded = true;
+
+ if (oldRoot == null) {
+ SetState(0);
+ stateList.Items[0].Selected = true;
+ SetColumnSizes();
+ } else {
+ var mapping = new Dictionary<SkeletonItem, SkeletonItem>();
+ unfoldingRoot.SyncWith(mapping, oldRoot);
+ SkeletonItem newIt = null;
+ while (selectedSkel != null) {
+ if (mapping.TryGetValue(selectedSkel, out newIt)) break;
+ selectedSkel = selectedSkel.parent;
+ }
+ if (CurrentState >= stateList.Items.Count)
+ CurrentState = 0;
+ if (PreviousState >= stateList.Items.Count)
+ PreviousState = -1;
+ if (newIt != null) GotoNode(newIt);
+ SyncStateListValues();
+ UpdateMatches(true);
+ }
+ }
+
+ private void SetColumnSizes()
+ {
+ currentStateView.Columns[0].Width = currentStateView.Width - currentStateView.Columns[1].Width - currentStateView.Columns[2].Width - 25;
+ stateList.Columns[1].Width = stateList.Width - stateList.Columns[0].Width - stateList.Columns[2].Width - 25;
+ }
+
+ public void SetState(int id, bool updateView = false)
+ {
+ if (updateView)
+ {
+ stateList.SelectedIndices.Clear();
+ stateList.SelectedIndices.Add(id);
+ }
+ if (CurrentState != id) {
+ PreviousState = CurrentState;
+ CurrentState = id;
+ }
+ UpdateMatches(true);
+ }
+
+ public void HideStateList()
+ {
+ stateList.Hide();
+ splitContainer1.Panel2.Hide();
+ splitContainer1.Panel2Collapsed = true;
+ splitContainer1.SplitterDistance = splitContainer1.Width;
+ }
+
+ public void HideMenuStrip()
+ {
+ menuStrip1.Hide();
+ }
+
+ internal void Activate(TreeNode treeNode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
+ {
+
+ }
+
+ static Color Col(int c)
+ {
+ return Color.FromArgb(c >> 16, (c >> 8) & 0xff, c & 0xff);
+ }
+
+ static StringFormat center = new StringFormat() { Alignment = StringAlignment.Center };
+ static Pen plusPen = new Pen(Col(0xaaaaaa));
+ static Brush grayedOut = new SolidBrush(Col(0xaaaaaa));
+ static Brush nonPrimary = new SolidBrush(Col(0xeeeeee));
+ static Brush matchBg = new SolidBrush(Col(0xFFFA6F));
+
+ static SolidBrush currentStateBrush = new SolidBrush(Color.Red);
+ static SolidBrush regularStateBrush = new SolidBrush(Color.Black);
+ static SolidBrush previousStateBrush = new SolidBrush(Color.Blue);
+
+ static SolidBrush[] categoryBrushes = new SolidBrush[] {
+ new SolidBrush(Color.Black), // Local
+ new SolidBrush(Color.Black), // PhysField
+ new SolidBrush(Color.Green), // SpecField
+ new SolidBrush(Color.Peru), // MethodologyProperty
+ new SolidBrush(Color.Green), // UserFunction
+ new SolidBrush(Color.Black), // Maplet
+ };
+
+ private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
+ {
+ var item = (DisplayItem)e.Item;
+ var skel = item.skel;
+ var rect = e.Bounds;
+ var listView = (ListView)sender;
+ lineHeight = rect.Height;
+ rect.Y += 1;
+ rect.Height -= 2;
+
+ var textBrush = Brushes.Black;
+ if (listView.SelectedIndices.Count > 0 && listView.SelectedIndices[0] == e.ItemIndex) {
+ e.Graphics.FillRectangle(Brushes.Aquamarine, rect);
+ textBrush = Brushes.White;
+ } else {
+ var bg = Brushes.White;
+ if (item.active && !skel.isPrimary[CurrentState])
+ bg = nonPrimary;
+ if (item.skel.isMatch)
+ bg = matchBg;
+ e.Graphics.FillRectangle(bg, rect);
+ }
+
+ var off = lineHeight * item.skel.level;
+ if (item.IsMatchListItem)
+ off = 0;
+
+ {
+ var plusRect = rect;
+ plusRect.Width = lineHeight;
+ plusRect.X += off;
+ var plusBorder = plusRect;
+ plusBorder.Height = lineHeight / 2;
+ plusBorder.Width = lineHeight / 2;
+ plusBorder.X += lineHeight / 4;
+ plusBorder.Y += lineHeight / 4;
+ e.Graphics.DrawRectangle(plusPen, plusBorder);
+ if (skel.Expandable) {
+ float midX = plusBorder.X + plusBorder.Width / 2;
+ float midY = plusBorder.Y + plusBorder.Height / 2;
+ e.Graphics.DrawLine(plusPen, plusBorder.X + 2, midY, plusBorder.Right - 2, midY);
+ if (!item.skel.expanded)
+ e.Graphics.DrawLine(plusPen, midX, plusBorder.Y + 2, midX, plusBorder.Bottom - 2);
+ }
+ }
+
+ off += lineHeight + 3;
+ var nameRect = rect;
+ var font = listView.Font;
+
+ textBrush = categoryBrushes[(int)item.dispNode.Category];
+
+ if (!item.active)
+ textBrush = grayedOut;
+
+ nameRect.Width = listView.Columns[0].Width - 1 - off;
+ nameRect.X += off;
+ var width = DrawString(e.Graphics, item.SubItems[0].Text, font, textBrush, nameRect);
+
+ textBrush = item.active ? Brushes.Black : grayedOut;
+ nameRect.X += width + 4;
+ nameRect.Width = listView.Columns[0].Width + listView.Columns[1].Width - nameRect.X;
+ width = DrawString(e.Graphics, item.SubItems[1].Text, font, textBrush, nameRect);
+
+ nameRect.X += width + 4;
+ nameRect.Width = listView.Width - nameRect.X;
+ var t = item.SubItems[2].Text;
+ width = DrawString(e.Graphics, t, font, t == item.SubItems[1].Text ? grayedOut : Brushes.Black, nameRect);
+ }
+
+ private int DrawString(Graphics g, string s, Font font, Brush textBrush, Rectangle minRect)
+ {
+ var sz = g.MeasureString(s, font).Width;
+ if (sz > minRect.Width - 2) {
+ minRect.Width = (int)(sz + 20);
+ }
+ g.DrawString(s, font, textBrush, minRect);
+ return minRect.Width;
+ }
+
+ private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
+ {
+ e.DrawBackground();
+ var brush = regularStateBrush;
+ if (e.Header.Index == 1)
+ brush = currentStateBrush;
+ else if (e.Header.Index == 2)
+ brush = previousStateBrush;
+
+ Rectangle r = e.Bounds;
+ r.X += 5;
+ r.Y += 4;
+ DrawString(e.Graphics, e.Header.Text, e.Header.ListView.Font, brush, r);
+ }
+
+ private void listView1_MouseUp(object sender, MouseEventArgs e)
+ {
+ var clickedItem = (DisplayItem)currentStateView.GetItemAt(5, e.Y);
+ if (clickedItem != null) {
+ clickedItem.Selected = true;
+ clickedItem.Focused = true;
+
+ var skel = clickedItem.skel;
+ int plusLoc = skel.level * lineHeight;
+ if (skel.Expandable && e.X >= plusLoc && e.X <= plusLoc + lineHeight) {
+ skel.Expanded = !skel.Expanded;
+ SyncCurrentStateView();
+ }
+ }
+ }
+
+ private void SyncCurrentStateView()
+ {
+ SyncListView(unfoldingRoot.RecChildren, currentStateView, (x, y) => { });
+ }
+
+ private void SyncListView(IEnumerable<SkeletonItem> items, ListView listView, Action<DisplayItem, SkeletonItem> cb)
+ {
+ var ch = items.ToArray();
+ var missing = ch.Length - listView.Items.Count;
+ listView.BeginUpdate();
+ if (missing < 0) {
+ missing = -missing;
+ while (missing-- > 0) {
+ listView.Items.RemoveAt(listView.Items.Count - 1);
+ }
+ } else {
+ while (missing-- > 0) {
+ listView.Items.Add(new DisplayItem());
+ }
+ }
+ for (int i = 0; i < ch.Length; ++i) {
+ var di = (DisplayItem)listView.Items[i];
+ cb(di, ch[i]);
+ di.Set(ch[i], CurrentState, PreviousState);
+ }
+ listView.EndUpdate();
+ listView.Invalidate();
+ }
+
+ private void listView1_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
+ {
+ currentStateView.Invalidate();
+ }
+
+ private void listView1_Resize(object sender, EventArgs e)
+ {
+ SetColumnSizes();
+ currentStateView.Invalidate();
+ }
+
+ private void stateList_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (stateList.SelectedItems.Count == 0) return;
+ var sel = stateList.SelectedItems[0].Index;
+
+ if (PreviousState >= 0)
+ stateList.Items[PreviousState].ForeColor = regularStateBrush.Color;
+
+ SetState(sel);
+ }
+
+ DisplayItem SelectedNode()
+ {
+ if (currentStateView.SelectedItems.Count == 0) return null;
+ return (DisplayItem)currentStateView.SelectedItems[0];
+ }
+
+ private void currentStateView_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ SyncStateListValues();
+ }
+
+ private void SyncStateListValues()
+ {
+ var sel = SelectedNode();
+ if (sel == null) return;
+
+ stateList.BeginUpdate();
+ for (int i = 0; i < sel.skel.displayNodes.Length; ++i) {
+ var dn = sel.skel.displayNodes[i];
+ stateList.Items[i].SubItems[2].Text = dn == null ? "" : dn.Value;
+ }
+ stateList.EndUpdate();
+ }
+
+ private void ExpandParents(SkeletonItem item)
+ {
+ item = item.parent;
+ while (item != null) {
+ item.Expanded = true;
+ item = item.parent;
+ }
+ }
+
+ private void textBox1_TextChanged(object sender, EventArgs e)
+ {
+ UpdateMatches(false);
+ }
+
+ private void UpdateMatches(bool force)
+ {
+ var bad = false;
+ Model.Element eltEq = null;
+ var eltRef = new List<Model.Element>();
+ var words = new List<string>();
+
+ foreach (var w in textBox1.Text.Split(' ')) {
+ if (w == "") continue;
+ if (w.StartsWith("eq:")) {
+ if (eltEq != null) bad = true;
+ else {
+ eltEq = LangModel.FindElement(w.Substring(3));
+ if (eltEq == null) bad = true;
+ }
+ } else if (w.StartsWith("use:")) {
+ var e = LangModel.FindElement(w.Substring(4));
+ if (e == null) bad = true;
+ else eltRef.Add(e);
+ } else {
+ words.Add(w.ToLower());
+ }
+ }
+
+ textBox1.ForeColor = bad ? Color.Red : Color.Black;
+
+ var wordsA = words.ToArray();
+ var refsA = eltRef.ToArray();
+
+ if (eltEq == null && wordsA.Length == 0 && refsA.Length == 0)
+ bad = true;
+
+ var changed = true; // force;
+ var matches = new List<SkeletonItem>();
+
+ foreach (var s in allItems) {
+ var newMatch = false;
+ if (s.isPrimary[CurrentState] && !bad) {
+ newMatch = s.MatchesWords(wordsA, refsA, eltEq, CurrentState);
+ }
+ if (newMatch)
+ matches.Add(s);
+ if (s.isMatch != newMatch) {
+ changed = true;
+ s.isMatch = newMatch;
+ }
+ }
+
+ if (PreviousState >= 0)
+ stateList.Items[PreviousState].ForeColor = previousStateBrush.Color;
+ stateList.Items[CurrentState].ForeColor = currentStateBrush.Color;
+
+ if (changed) {
+ SyncListView(matches, matchesList, (di, _) => { di.IsMatchListItem = true; });
+ SyncCurrentStateView();
+ }
+ }
+
+ private void matchesList_Resize(object sender, EventArgs e)
+ {
+ matchesList.Invalidate();
+ }
+
+ private void matchesList_DoubleClick(object sender, EventArgs e)
+ {
+ if (matchesList.SelectedItems.Count == 0) return;
+ var sel = (DisplayItem)matchesList.SelectedItems[0];
+ GotoNode(sel.skel);
+ }
+
+ private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+ {
+ foreach (DisplayItem it in matchesList.Items) {
+ ExpandParents(it.skel);
+ }
+ SyncCurrentStateView();
+ }
+
+ private void SetSearch(string text)
+ {
+ textBox1.Text = text;
+ }
+
+ private void GotoNode(SkeletonItem skel)
+ {
+ ExpandParents(skel);
+ SyncCurrentStateView();
+ foreach (DisplayItem it in currentStateView.Items) {
+ if (it.skel == skel) {
+ it.Selected = true;
+ currentStateView.EnsureVisible(it.Index);
+ break;
+ }
+ }
+ }
+
+ private IEnumerable<SkeletonItem> NamesFor(Model.Element elt)
+ {
+ var words = new string[0];
+ var elts = new Model.Element[0];
+
+ foreach (var s in allItems) {
+ if (s.isPrimary[CurrentState] && s.MatchesWords(words, elts, elt, CurrentState)) {
+ yield return s;
+ }
+ }
+ }
+
+ private void AddMenuItems(IEnumerable<SkeletonItem> skels, ToolStripItemCollection items, string pref, int max)
+ {
+ var skelsM = skels.Take(max).ToArray();
+
+ foreach (var s in skelsM) {
+ var tmp = s;
+ items.Add(pref + s.LongName(CurrentState), null, (x, _) => GotoNode(tmp));
+ }
+
+ if (skelsM.Length == max)
+ items.Add(new ToolStripMenuItem("...") { Enabled = false });
+ }
+
+ private void stateViewMenu_Opening(object sender, CancelEventArgs e)
+ {
+ IDisplayNode sel = null;
+ SkeletonItem skel = null;
+ if (SelectedNode() != null) {
+ sel = SelectedNode().dispNode;
+ skel = SelectedNode().skel;
+ }
+
+ var items = stateViewMenu.Items;
+ items.Clear();
+
+ if (sel == null) {
+ items.Add(new ToolStripMenuItem("Unavailable") { Enabled = false });
+ return;
+ }
+
+ foreach (var x in sel.References.Where(q => q != sel.Element)) {
+ var t = new ToolStripMenuItem(LangModel.CanonicalName(x));
+ items.Add(t);
+ AddMenuItems(NamesFor(x), t.DropDownItems, "= ", 20);
+ }
+
+ if (sel.Element != null) {
+ var selName = LangModel.CanonicalName(sel.Element);
+ items.Add("Find uses...", null, (s, _) => SetSearch("use:" + selName));
+
+ var aliases = NamesFor(sel.Element).Where(s => s != skel).ToArray();
+ if (aliases.Length > 0) {
+ items.Add("Aliases...", null, (s, _) => SetSearch("eq:" + selName));
+ AddMenuItems(aliases, items, " = ", 10);
+ }
+ }
+ }
+
+ private void normalToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ int viewLev = -1;
+ for (int i = 0; i < viewItems.Length; ++i) {
+ if (viewItems[i] == sender) {
+ viewLev = i;
+ viewItems[i].Checked = true;
+ } else {
+ viewItems[i].Checked = false;
+ }
+ }
+ if (viewLev != -1 && viewLev != viewOpts.ViewLevel) {
+ viewOpts.ViewLevel = viewLev;
+ BuildModel();
+ }
+ }
+
+ private void debugToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ debugToolStripMenuItem.Checked = !debugToolStripMenuItem.Checked;
+ viewOpts.DebugMode = debugToolStripMenuItem.Checked;
+ BuildModel();
+ }
+
+ private void exitToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+
+ private void reloadModelFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ ReadModels(this.lastModelFileName, this.modelId);
+ }
+
+ private SourceView sourceView;
+ private void ShowSource()
+ {
+ if (stateList.SelectedItems.Count == 0) return;
+ var li = stateList.SelectedItems[0] as ListViewItem;
+ if (li != null) {
+ var r = ((IState)li.Tag).ShowSource();
+ if (r != null) {
+ if (sourceView == null) {
+ sourceView = new SourceView();
+ }
+ sourceView.largeFont = largeFontToolStripMenuItem.Checked;
+ sourceView.SetSourceLocation(r);
+ sourceView.BringToFront();
+ }
+ }
+ }
+
+ private void showSourceToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ ShowSource();
+ }
+
+ private void stateList_DoubleClick(object sender, EventArgs e)
+ {
+ ShowSource();
+ }
+
+ private void openModelMenuItem_Click(object sender, EventArgs e)
+ {
+ if (this.openModelFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
+ this.ReadModels(this.openModelFileDialog.FileName, 0);
+ }
+ }
+
+ private void largeFontToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ largeFontToolStripMenuItem.Checked = !largeFontToolStripMenuItem.Checked;
+
+ if (largeFont == null) {
+ largeFont = new Font(smallFont.FontFamily, smallFont.Size * 2, smallFont.Unit);
+ }
+
+ SetFont(largeFontToolStripMenuItem.Checked ? largeFont : smallFont);
+ //textBox1.Font = font;
+ //linkLabel1.Font = font;
+ //label1.Font = font;
+ }
+
+ public void SetFont(System.Drawing.Font font)
+ {
+ stateList.Font = font;
+ currentStateView.Font = font;
+ matchesList.Font = font;
+ }
+
+ private void Main_Load(object sender, EventArgs e)
+ {
+
+ }
+
+ private void currentStateView_KeyDown(object sender, KeyEventArgs e)
+ {
+ var node = SelectedNode();
+ if (node == null) return;
+
+ if (e.KeyCode == Keys.Right && !node.skel.Expanded && node.skel.Expandable) {
+ node.skel.Expanded = true;
+ SyncCurrentStateView();
+ return;
+ }
+
+ if (e.KeyCode == Keys.Left) {
+ if (node.skel.Expanded) {
+ node.skel.Expanded = false;
+ SyncCurrentStateView();
+ return;
+ } else {
+ var par = node.skel.parent;
+ if (par != null && par.parent != null) {
+ // par.Expanded = false;
+ foreach (DisplayItem it in currentStateView.Items) {
+ it.Selected = it.skel == par;
+ it.Focused = it.skel == par;
+ if (it.Selected) {
+ it.EnsureVisible();
+ }
+ }
+ SyncCurrentStateView();
+ }
+ }
+ }
+ }
+ }
+
+ internal class DisplayItem : ListViewItem
+ {
+ internal SkeletonItem skel;
+ internal int stateId;
+ internal bool active;
+ internal IDisplayNode dispNode;
+
+ public bool IsMatchListItem { get; set; }
+
+ internal void Set(SkeletonItem s, int id, int prevId)
+ {
+ if (skel == s && stateId == id)
+ return;
+ skel = s;
+ stateId = id;
+
+ dispNode = skel.displayNodes[stateId];
+ active = dispNode != null;
+
+ var closeStateId = stateId;
+
+ if (dispNode == null) {
+ while (closeStateId < skel.displayNodes.Length && skel.displayNodes[closeStateId] == null)
+ closeStateId++;
+ if (closeStateId >= skel.displayNodes.Length) {
+ closeStateId = stateId;
+ while (closeStateId >= 0 && skel.displayNodes[closeStateId] == null)
+ closeStateId--;
+ }
+ dispNode = skel.displayNodes[closeStateId];
+ }
+
+ var fullName = skel.LongName(closeStateId);
+ var tooltip = dispNode.ToolTip;
+ if (tooltip == null)
+ tooltip = "";
+ if(tooltip.Length > 0 && tooltip[tooltip.Length - 1] != '\n')
+ tooltip += "\n";
+ tooltip += "Full name: " + fullName;
+ if (tooltip != null) {
+ this.ToolTipText = tooltip;
+ }
+
+ var name = dispNode.Name;
+ if (name != dispNode.ShortName)
+ {
+ name = dispNode.ShortName;
+ }
+
+ if (IsMatchListItem) {
+ Util.Assert(active);
+ name = fullName;
+ }
+
+ this.SubItems[0].Text = name;
+ this.SubItems[1].Text = active ? dispNode.Value : "";
+
+ var prev = "";
+
+ if (!IsMatchListItem && prevId >= 0 && skel.displayNodes[prevId] != null) {
+ prev = skel.displayNodes[prevId].Value;
+ }
+
+ this.SubItems[2].Text = prev;
+ }
+
+ internal DisplayItem()
+ : base(new string[] { "", "", "" })
+ {
+ }
+
+ /*
+ static internal string AliasesAsString(IDisplayNode dn)
+ {
+ if (dn == null) return "";
+
+ var sb = new StringBuilder();
+ var canon = dn.CanonicalValue;
+ foreach (var n in dn.Aliases) {
+ if (n == canon)
+ continue;
+ sb.Append(n).Append(", ");
+ if (sb.Length > 300)
+ break;
+ }
+ if (sb.Length > 2) sb.Length -= 2;
+ return sb.ToString();
+ }
+ */
+ }
+}