1 using System;
  2 using System.Windows;
  3 using System.IO;
  4 using System.Collections;
  5 using System.Xml.Serialization;
  6 using Cm.Views;
  7 
  8 class MainWindow : Window
  9 {
 10     public MainWindow() : base("Abstract Syntax Tree Viewer")
 11     {
 12         UniquePtr<MenuBar> menuBar(new MenuBar());
 13         UniquePtr<MenuItem> fileItem(new MenuItem("&File"));
 14         UniquePtr<MenuItem> openItem(new MenuItem("&Open..."));
 15         openItem->SetShortcut(Keys.f3);
 16         openItem->ClickEvent().AddHandler(OpenClick);
 17         fileItem->AddMenuItem(openItem.Release());
 18         fileItem->AddMenuItem(new MenuItemSeparator());
 19         UniquePtr<MenuItem> exitMenuItem(new MenuItem("E&xit"));
 20         exitMenuItem->SetShortcut(cast<Keys>(Keys.altModifier | Keys.f4));
 21         exitMenuItem->ClickEvent().AddHandler(ExitClick);
 22         fileItem->AddMenuItem(exitMenuItem.Release());
 23         menuBar->AddMenuItem(fileItem.Release());
 24         UniquePtr<MenuItem> viewItem(new MenuItem("&View"));
 25         UniquePtr<MenuItem> updateItem(new MenuItem("&Update tree view"));
 26         updateItem->SetShortcut(cast<Keys>(Keys.controlModifier | Keys.u));
 27         updateItem->ClickEvent().AddHandler(UpdateClick);
 28         viewItem->AddMenuItem(updateItem.Release());
 29         menuBar->AddMenuItem(viewItem.Release());
 30         AddChild(menuBar.Release());
 31         UniquePtr<SplitContainer> verticalSplitContainer;
 32         UniquePtr<LogView> logView;
 33         if (Debug.Log())
 34         {
 35             verticalSplitContainer.Reset(new SplitContainer(Orientation.vertical400Point(00)Size(00)Dock.fillAnchors.none));
 36             logView.Reset(new LogView());
 37             logView->SetScrollSubject();
 38             Application.SetLogView(logView.Get());
 39             UniquePtr<Control> borderedLogView(new BorderedControl(logView.Release()BorderStyle.style3DPoint(00)Size(00)Dock.noneAnchors.none));
 40             UniquePtr<Control> scrollableLogView(new ScrollableControl(borderedLogView.Release()Point(00)Size(00)Dock.fillAnchors.none));
 41             verticalSplitContainer->Pane2Container()->AddChild(scrollableLogView.Release());
 42         }
 43         UniquePtr<SplitContainer> horizontalSplitContainer(new SplitContainer(Orientation.horizontal600Point(00)Size(00)Dock.fillAnchors.none));
 44         treeView = new TreeView(TreeViewCreateParams(TreeViewControlCreateParams(ControlCreateParams().Defaults())).Defaults());
 45         //treeView = new TreeView(Point(0, 0), Size(0, 0), Dock.none, Anchors.none);
 46         treeView->NodeDoubleClickEvent().AddHandler(TreeViewNodeDoubleClick);
 47         treeView->SetScrollSubject();
 48         treeView->NodeEnterEvent().AddHandler(TreeViewNodeEnter);
 49         treeView->NodeLeaveEvent().AddHandler(TreeViewNodeLeave);
 50         treeView->NodeSelectedEvent().AddHandler(TreeViewNodeSelected);
 51         UniquePtr<Control> paddedTreeView(new PaddedControl(treeViewPadding(4444)Point(00)Size(00)Dock.noneAnchors.none));
 52         UniquePtr<Control> borderedTreeView(new BorderedControl(paddedTreeView.Release()BorderStyle.style3DPoint(00)Size(00)Dock.noneAnchors.none));
 53         UniquePtr<Control> scrollableTreeView(new ScrollableControl(borderedTreeView.Release()Point(00)Size(00)Dock.fillAnchors.none));
 54         horizontalSplitContainer->Pane1Container()->AddChild(scrollableTreeView.Release());
 55         sourceCodeView = new CmajorSourceCodeView(Point(00)Size(00)Dock.fillAnchors.none);
 56         sourceCodeView->SetScrollSubject();
 57         sourceCodeView->CaretPosChangedEvent().AddHandler(CaretPosChanged);
 58         UniquePtr<Control> paddedSourceCodeView(new PaddedControl(sourceCodeViewPadding(4444)Point(00)Size(00)Dock.noneAnchors.none));
 59         UniquePtr<Control> borderedSourceCodeView(new BorderedControl(paddedSourceCodeView.Release()BorderStyle.style3DPoint(00)Size(00)Dock.noneAnchors.none));
 60         UniquePtr<Control> scrollableSourceCodeView(new ScrollableControl(borderedSourceCodeView.Release()Point(00)Size(00)Dock.fillAnchors.none));
 61         horizontalSplitContainer->Pane2Container()->AddChild(scrollableSourceCodeView.Release());
 62         if (verticalSplitContainer.IsNull())
 63         {
 64             AddChild(horizontalSplitContainer.Release());
 65         }
 66         else
 67         {
 68             verticalSplitContainer->Pane1Container()->AddChild(horizontalSplitContainer.Release());
 69             AddChild(verticalSplitContainer.Release());
 70         }
 71     }
 72     public override void PrintWindowTree(int level)
 73     {
 74         LogView* log = Application.GetLogView();
 75         if (log != null)
 76         {
 77             log->WriteLine("MainWindow." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + ParentText() + "[" + Rect(Location()GetSize()).ToString() + "]");
 78         }
 79         Component* child = Children().FirstChild();
 80         while (child != null)
 81         {
 82             if (child is Control*)
 83             {
 84                 Control* childControl = cast<Control*>(child);
 85                 childControl->PrintWindowTree(level + 1);
 86             }
 87             child = child->NextSibling();
 88         }
 89     }
 90     protected override void OnKeyDown(KeyEventArgs& args)
 91     {
 92         base->OnKeyDown(args);
 93         if (!args.handled && args.key == cast<Keys>(Keys.altModifier | Keys.c))
 94         {
 95             LogView* logView = Application.GetLogView();
 96             if (logView != null)
 97             {
 98                 logView->Clear();
 99             }
100         }
101     }
102     private void ExitClick()
103     {
104         Close();
105     }
106     private void OpenClick()
107     {
108         try
109         {
110             List<Pair<stringstring>> descriptionFilterPairs;
111             descriptionFilterPairs.Add(Pair<stringstring>("Cmajor source files (*.cm)""*.cm"));
112             string initialDirectory;
113             const char* cmajorRoot = RtGetEnvironmentVariable("CMAJOR_ROOT");
114             string defaultFilePath;
115             if (cmajorRoot != null && *cmajorRoot != '\0')
116             {
117                 initialDirectory = cmajorRoot;
118             }
119             string filePath;
120             string currentDirectory;
121             List<string> fileNames;
122             bool selected = System.Windows.API.GetOpenFileName(Handle()descriptionFilterPairsinitialDirectorydefaultFilePath".cm"
123                 OFN_PATHMUSTEXIST | OFN_FILEMUSTEXISTcurrentDirectoryfileNames);
124             if (selected)
125             {
126                 if (!fileNames.IsEmpty())
127                 {
128                     filePath = Path.Combine(currentDirectoryfileNames[0]);
129                 }
130                 if (!filePath.IsEmpty() && File.Exists(filePath))
131                 {
132                     treeView->SetRoot(null);
133                     content = ToUtf32(File.ReadAllText(filePath));
134                     lexer = CmajorLexer(content.Chars()content.Chars() + content.Length()filePath0);
135                     Cm.Parser.ParsingContext ctx;
136                     compileUnit = CompileUnitParser.Parse(lexer&ctx);
137                     SyntaxTreeBuilder syntaxTreeBuilder(lexer);
138                     compileUnit->Accept(syntaxTreeBuilder);
139                     indexNodeMap = syntaxTreeBuilder.GetIndexNodeMap();
140                     for (const Pair<intTreeViewNode*>& p : indexNodeMap)
141                     {
142                         indexNodeList.Add(p);
143                     }
144                     Sort(indexNodeList.Begin()indexNodeList.End());
145                     nodeIndexMap = syntaxTreeBuilder.GetNodeIndexMap();
146                     treeView->SetRoot(syntaxTreeBuilder.GetRoot());
147                     sourceCodeView->SetTextContent(content);
148                     sourceCodeView->SetFocus();
149                 }
150                 else
151                 {
152                     throw Exception("file path is empty or does not exist");
153                 }
154             }
155         }
156         catch (const Exception& ex)
157         {
158             MessageBox.Show(ex.Message());
159         }
160     }
161     private void TreeViewNodeDoubleClick(TreeViewNodeMouseClickEventArgs& args)
162     {
163         TreeViewNode* node = args.node;
164         switch (node->GetState())
165         {
166             case TreeViewNode.State.collapsed: node->ExpandAll(); break;
167             case TreeViewNode.State.expanded: node->CollapseAll(); break;
168         }
169     }
170     private void TreeViewNodeEnter(TreeViewNodeEventArgs& args)
171     {
172         TreeViewNode* treeViewNode = args.node;
173         if (treeViewNode->Data() != null)
174         {
175             Cm.Ast.Node* node = cast<Cm.Ast.Node*>(treeViewNode->Data());
176             SyntaxNodeAttributeExtractor attributeExtractor;
177             node->Accept(attributeExtractor);
178             treeView->ShowToolTipWindow(attributeExtractor.streeViewNode);
179         }
180     }
181     private void TreeViewNodeLeave(TreeViewNodeEventArgs& args)
182     {
183         TreeViewNode* node = args.node;
184         treeView->HideToolTipWindow();
185     }
186     private void TreeViewNodeSelected(TreeViewNodeEventArgs& args)
187     {
188         TreeViewNode* node = args.node;
189         HashMap<TreeViewNode*int>.ConstIterator it = nodeIndexMap.CFind(node);
190         if (it != nodeIndexMap.CEnd())
191         {
192             int index = it->second;
193             LogView* logView = Application.GetLogView();
194             if (logView != null)
195             {
196                 logView->WriteLine("index=" + ToString(index));
197             }
198             sourceCodeView->SetFocus();
199             sourceCodeView->SetCaretPosByCharIndex(index);
200         }
201     }
202     private void UpdateClick()
203     {
204         int caretLine = sourceCodeView->CaretLine();
205         int caretColumn = sourceCodeView->CaretColumn();
206         int index = sourceCodeView->GetCharIndex(caretLinecaretColumn);
207         if (index != -1)
208         {
209             Pair<intTreeViewNode*> x(indexnull);
210             List<Pair<intTreeViewNode*>>.ConstIterator it = LowerBound(indexNodeList.CBegin()indexNodeList.CEnd()x);
211             if (it != indexNodeList.CBegin() && it == indexNodeList.CEnd())
212             {
213                 --it;
214             }
215             int i = -1;
216             if (it != indexNodeList.CEnd())
217             {
218                 int i = it->first;
219                 if (i > index)
220                 {
221                     if (it != indexNodeList.CBegin())
222                     {
223                         --it;
224                     }
225                 }
226             }
227             if (it != indexNodeList.CEnd())
228             {
229                 TreeViewNode* node = it->second;
230                 treeView->Root()->CollapseAll();
231                 TreeViewNode* p = node;
232                 while (p != null)
233                 {
234                     p->Expand();
235                     p = p->Parent();
236                 }
237                 treeView->Invalidate();
238                 treeView->Update();
239                 node->EnsureVisible();
240                 treeView->Invalidate();
241             }
242         }
243     }
244     private void CaretPosChanged()
245     {
246         int caretLine = sourceCodeView->CaretLine();
247         int caretColumn = sourceCodeView->CaretColumn();
248         LogView* logView = Application.GetLogView();
249         if (logView != null)
250         {
251             logView->WriteLine("caret: (" + ToString(caretLine) + ", " + ToString(caretColumn) + ")");
252         }
253     }
254     private TreeView* treeView;
255     private CmajorSourceCodeView* sourceCodeView;
256     private ustring content;
257     private CmajorLexer lexer;
258     private UniquePtr<Cm.Ast.CompileUnitNode> compileUnit;
259     private HashMap<intTreeViewNode*> indexNodeMap;
260     private List<Pair<intTreeViewNode*>> indexNodeList;
261     private HashMap<TreeViewNode*int> nodeIndexMap;
262 }
263 
264 int main()
265 {
266     try
267     {
268         //Debug.SetLog();
269         //Debug.SetDocking();
270         //Debug.SetWindowTree();
271         //Debug.SetPaint();
272 
273         MainWindow mainWindow;
274         mainWindow.SetSmallIcon(Application.GetResourceManager().GetIcon("astviewer.icon"));
275         if (Debug.WindowTree())
276         {
277             mainWindow.PrintWindowTree(0);
278         }
279         int exitCode = Application.Run(mainWindow);
280         return exitCode;
281     }
282     catch (const Exception& ex)
283     {
284         MessageBox.Show(ex.Message()"Error"nullcast<MessageBoxType>(MessageBoxType.MB_OK | MessageBoxType.MB_ICONSTOP));
285         try
286         {
287             StreamWriter errorWriter = File.CreateText("error.txt");
288             errorWriter << ex.ToString() << endl();
289         }
290         catch (const Exception&)
291         {
292         }
293         return 1;
294     }
295     return 0;
296 }