private void Btn_delete_item_Click(object sender, RoutedEventArgs e) { // First: Ask the user if he is reaaaally sure if (this.MessageBoxShow("Do you want to delete this snippet?", "Confirmation", Buttons.YesNo, Icons.Warning, AnimateStyle.FadeIn) == System.Windows.Forms.DialogResult.No) { return; } SnippetNode selectedNode = ((Button)sender).DataContext as SnippetNode; TabItem openTab = tbc_pages.Items.Cast <TabItem>().FirstOrDefault(t => t.Content is SnippetPage p && p.ShownSnippet == selectedNode.Tag); if (openTab != null) { /* Check if to-be-deleted tab is currently selected..*/ if ((tbc_pages.SelectedContent as SnippetPage).ShownSnippet == selectedNode.Tag) { /* .. and select the previous one if that is the case */ tbc_pages.SelectedIndex -= 1; } /* Afterwards: Remove it */ tbc_pages.Items.Remove(openTab); } /* .. and manually delete snippet from tree instead of refreshing the whole tree */ shownSnippetMetaListGroups.FirstOrDefault(node => node.ChildNodes.Contains(selectedNode)).ChildNodes.Remove(selectedNode); selectedNode.Tag.delete(); }
private void btn_like_item_Click(object sender, RoutedEventArgs e) { SnippetNode selectedNode = ((ToggleButton)sender).DataContext as SnippetNode; selectedNode.Tag.Favorite = ((ToggleButton)sender).IsChecked ?? false; selectedNode.Tag.save(); refreshNodesAsync().ConfigureAwait(false); }
/// <summary> /// build treeview and its inner groups /// //TODO: Also call this if there was a database call. Maybe over a custom event? /// </summary> private async Task refreshNodesAsync() { string filter = tb_search.Text; // Maybe a bit of wait time for the database - thus: asynchronous List <ITreeNode> newList = await Task.Run(() => { newList = new List <ITreeNode>(); foreach (SnippetInfo s in App.DatabaseInstance.GetSnippetMetaList()) { ITreeNode currentGroup; if (String.IsNullOrEmpty(s.LanguageTag.Title)) { currentGroup = newList.FirstOrDefault(n => n.HasEmptyTitle); } else { currentGroup = newList.FirstOrDefault(n => n.Title == s.LanguageTag.Title); } // if a top node contains programming language.. if (currentGroup == null) { currentGroup = new SnippetNode() { Title = s.LanguageTag.Title, IsGroup = true }; newList.Add(currentGroup); } // add the new node to that one if it shouldn't be hidden currentGroup.ChildNodes.Add(new SnippetNode() { Title = s.Titel, Tag = s, IsVisible = shouldNodeShow(s, filter) }); } // sort all group content foreach (ITreeNode group in newList) { group.ChildNodes = new ObservableCollection <ITreeNode>(group.ChildNodes.OrderByDescending(node => ((SnippetNode)node).Tag?.Favorite).ThenByDescending(node => ((SnippetNode)node).Tag?.LastEditDate)); } return(newList); }); // clear bound list before refreshing it and then // refresh it - assignment wouldn't work since the data binding would break shownSnippetMetaListGroups.AddRange(newList, true); // after refreshing, lookup if the currently selected tab needs to get a matching partner in the tree view again since all selections are cleared Tbc_pages_SelectionChanged(tv_snippetList, null); }
private void Tbc_pages_SelectionChanged(object sender, SelectionChangedEventArgs e) { TabItem selectedTab = tbc_pages.SelectedItem as TabItem; // due to a bug in wpf, we have to unselect the current item here already if (tv_snippetList.SelectedItem != null) { (tv_snippetList.SelectedItem as SnippetNode).IsSelected = false; } if (selectedTab?.Content is SnippetPage p) { // search for snippet in two levels SnippetNode snippetPosInTree = (SnippetNode)shownSnippetMetaListGroups.SelectMany(d => d.ChildNodes).FirstOrDefault(innernode => (innernode as SnippetNode).Tag == p.ShownSnippet); // if snippet was found.. if (snippetPosInTree != null) { // .. and unselect every node shownSnippetMetaListGroups.ToList().ForEach(node => node.deselectAll()); // .. and set found node as selected. snippetPosInTree.IsSelected = true; } if (String.IsNullOrEmpty(p.ShownSnippet.Titel)) { lbl_title_snippetName.Content = TITLE_UNNAMED; } else { lbl_title_snippetName.Content = p.ShownSnippet.Titel; } } else { lbl_title_snippetName.Content = selectedTab?.Header ?? ""; } // Adjust window title to show currently edited snippet name this.Title = "Snippet Man - " + lbl_title_snippetName.Content; }
private void Tv_snippetList_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { SnippetNode selectedNode = (SnippetNode)e.NewValue; if (selectedNode == null) { return; } // check if page is already open, if so: Select it TabItem openTab = tbc_pages.Items.Cast <TabItem>().FirstOrDefault(t => t.Content is SnippetPage p && p.ShownSnippet == selectedNode.Tag); if (openTab != null) { openTab.IsSelected = true; return; } if (selectedNode != null && !selectedNode.IsGroup) // can happen e.g. on clearing the list { addSnippetPage(selectedNode.Tag.withSnippetCodeUpdate()); } }
/// <summary> /// Interprets the abstract syntax of the TML document and generates semantic node representatives. /// </summary> /// <exception cref="FormatException">Thrown if an unexpected tag or a task number in an invalid format is encountered and if more than one subsnippet is active.</exception> private void ParseTML() { nodes.Clear(); //process all nodes of the abstract syntax tree foreach (var node in syntaxTree.Nodes) { var contentNode = node as TMLTerminalNode; var tagNode = node as TMLTagNode; //if the node is just content, add a new text node if (contentNode != null) { nodes.Add(new TextNode(contentNode)); } //if the node is a tag node, try to interpret it as a snippet else if (tagNode != null) { if (tagNode.TagName != "snippet") { throw new FormatException($"Did not expect tag {tagNode.TagName} here."); } //Create the semantic snippet node var snippetNode = new SnippetNode(); //Try to find the indentation of this snippet (everything that is a whitespace in front of the snippet tag) var startIndentIncl = tagNode.OpeningTagBeginIndex; Func <char, bool> isIndentation = (char c) => Char.IsWhiteSpace(c) && c != '\r' && c != '\n'; while (startIndentIncl > 0 && isIndentation(text[startIndentIncl - 1])) { --startIndentIncl; } snippetNode.Indentation = text.Substring(startIndentIncl, tagNode.OpeningTagBeginIndex - startIndentIncl); //Try to parse the task number string taskNumber; if (tagNode.Attributes.TryGetValue("task", out taskNumber)) { try { snippetNode.TaskNumber = HierarchicalNumber.ParseFromString(taskNumber); } catch (Exception x) { throw new FormatException($"Error parsing hierarchical number from {taskNumber}.", x); } } //Assign the existing subsnippets foreach (var subsnippet in subsnippets) { subsnippet.Key.SetValue(snippetNode, FindSubSnippet(tagNode, subsnippet.Value.TagName)); } //Check if there are invalid subtags if (tagNode.InnerNodes.Where(n => n is TMLTagNode).Select(n => (TMLTagNode)n).Any(n => !subsnippetTags.Contains(n.TagName))) { throw new FormatException("The snippet tag contains invalid subtags."); } if (!snippetNode.HasAtMostOneActiveSubSnippet) { throw new FormatException("More than one subsnippet have uncommented lines."); } nodes.Add(snippetNode); } } }