private void articleRichTextBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            bool ctrlIsDown = Keyboard.GetKeyStates(Key.LeftCtrl).HasFlag(KeyStates.Down) || Keyboard.GetKeyStates(Key.RightCtrl).HasFlag(KeyStates.Down);

            TextPointer pointer = articleRichTextBox.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox), false);

            //TextPointer pointer = m_articleParagraph.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox));
            Logic.TextInLanguage.SyntaxLayout.Word mouseOverWord;
            UICommon.GetWordFromPointer(pointer, Global.CurrentWorkspace.CurrentArticle.OriginalText, out mouseOverWord);

            if (m_articleMouseLeftButtonDownWord == mouseOverWord)
            {
                m_articleMouseLeftButtonDownWord = null;

                if (mouseOverWord != null)
                {
                    SelectWord(mouseOverWord, ctrlIsDown);
                }
                else if (!ctrlIsDown)
                {
                    ClearSelectedWords();
                }

                UpdateArticleVisualSelection(mouseOverWord);
            }
        }
        private void articleRichTextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            TextPointer pointer = articleRichTextBox.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox), false);

            //TextPointer pointer = m_articleParagraph.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox));
            Logic.TextInLanguage.SyntaxLayout.Word word;
            UICommon.GetWordFromPointer(pointer, Global.CurrentWorkspace.CurrentArticle.OriginalText, out word);

            m_articleMouseLeftButtonDownWord = word;
        }
        public void SelectWord(Logic.TextInLanguage.SyntaxLayout.Word word, bool multiSelect)
        {
            if (!multiSelect)
            {
                m_selectedWords.Clear();
                m_selectedWords.Add(word);
            }
            else
            {
                if (!m_selectedWords.Contains(word))
                {
                    m_selectedWords.Add(word);

                    // Упорядочим список выделенных слов по порядку следования в исходном тексте
                    m_selectedWords.Sort((a, b) => { return(a.FirstIndex.CompareTo(b.FirstIndex)); });
                }
                else
                {
                    m_selectedWords.Remove(word);
                }
            }

            OnSelectedWordsChange();
        }
        private void articleRichTextBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            bool ctrlIsDown = Keyboard.GetKeyStates(Key.LeftCtrl).HasFlag(KeyStates.Down) || Keyboard.GetKeyStates(Key.RightCtrl).HasFlag(KeyStates.Down);

            TextPointer pointer = articleRichTextBox.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox), false);
            //TextPointer pointer = m_articleParagraph.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox));
            Logic.TextInLanguage.SyntaxLayout.Word mouseOverWord;
            UICommon.GetWordFromPointer(pointer, Global.CurrentWorkspace.CurrentArticle.OriginalText, out mouseOverWord);

            if (m_articleMouseLeftButtonDownWord == mouseOverWord)
            {
                m_articleMouseLeftButtonDownWord = null;

                if (mouseOverWord != null)
                    SelectWord(mouseOverWord, ctrlIsDown);
                else if (!ctrlIsDown)
                    ClearSelectedWords();

                UpdateArticleVisualSelection(mouseOverWord);
            }
        }
        private void articleRichTextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            TextPointer pointer = articleRichTextBox.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox), false);
            //TextPointer pointer = m_articleParagraph.GetPositionFromPoint(Mouse.GetPosition(articleRichTextBox));
            Logic.TextInLanguage.SyntaxLayout.Word word;
            UICommon.GetWordFromPointer(pointer, Global.CurrentWorkspace.CurrentArticle.OriginalText, out word);

            m_articleMouseLeftButtonDownWord = word;
        }
        public static void GetWordFromPointer(TextPointer pointer, Logic.TextInLanguage textInLanguage, out Logic.TextInLanguage.SyntaxLayout.Word word)
        {
            if (pointer != null)
            {
                int letterIdx = GetTextIndexInParagraphFromPointer(pointer);

                Logic.TextInLanguage.SyntaxLayout.WordInSentenceIndex index;
                bool inWord   = textInLanguage.Layout.GetWordInSentenceIndexByTextLetterIndex(letterIdx, out index);
                var  wordData = textInLanguage.Layout.GetWordByIndex(index);

                if (inWord)
                {
                    word = wordData;
                }
                else
                {
                    word = null;
                }

                return;
            }

            word = null;
        }
        // Обновляет состояние выделений (форматом) текста в статье
        private void UpdateArticleVisualSelection(Logic.TextInLanguage.SyntaxLayout.Word mouseOverWord)
        {
            // Вычисляем сколько будет заданно различных выделений. Это нужно для того чтобы задать точный capacity, но если не совпадет - пофиг
            int selectionCount = m_translatedWords.Count + m_selectedWords.Count + m_unselectedPhraseWords.Count + m_wrongWords.Count + (mouseOverWord == null ? 0 : 2);

            List <FlowDocumentFormatter.Selection> selections = new List <FlowDocumentFormatter.Selection>(selectionCount);

            // Подсвечиваем переведенные слова
            for (int i = 0; i < m_translatedWords.Count; i++)
            {
                selections.Add(new FlowDocumentFormatter.Selection()
                {
                    fontColor  = m_textColorTranslated,
                    fontFamily = this.FontFamily,
                    fontSize   = articleFontSize,
                    range      = new FlowDocumentFormatter.Selection.Range()
                    {
                        firstIndex = m_translatedWords[i].FirstIndex,
                        lastIndex  = m_translatedWords[i].LastIndex
                    },
                    backgroundColor = Colors.White,
                    priority        = 0
                });
            }

            // Подсвечиваем выделенные слова
            for (int i = 0; i < m_selectedWords.Count; i++)
            {
                selections.Add(new FlowDocumentFormatter.Selection()
                {
                    fontColor  = Colors.Black,
                    fontFamily = this.FontFamily,
                    fontSize   = articleFontSize,
                    range      = new FlowDocumentFormatter.Selection.Range()
                    {
                        firstIndex = m_selectedWords[i].FirstIndex,
                        lastIndex  = m_selectedWords[i].LastIndex
                    },
                    backgroundColor = m_textColorBackRight,
                    priority        = 2
                });
            }

            // Подсвечиваем слова из фразы, которые не присутсвуют в выделении
            for (int i = 0; i < m_unselectedPhraseWords.Count; i++)
            {
                selections.Add(new FlowDocumentFormatter.Selection()
                {
                    fontColor  = m_textColorUnselectedPhrase,
                    fontFamily = this.FontFamily,
                    fontSize   = articleFontSize,
                    range      = new FlowDocumentFormatter.Selection.Range()
                    {
                        firstIndex = m_unselectedPhraseWords[i].FirstIndex,
                        lastIndex  = m_unselectedPhraseWords[i].LastIndex
                    },
                    backgroundColor = Colors.White,
                    priority        = 2
                });
            }

            // Подсвечиваем "неправильные" слова
            for (int i = 0; i < m_wrongWords.Count; i++)
            {
                selections.Add(new FlowDocumentFormatter.Selection()
                {
                    fontColor  = Colors.Black,
                    fontFamily = this.FontFamily,
                    fontSize   = articleFontSize,
                    range      = new FlowDocumentFormatter.Selection.Range()
                    {
                        firstIndex = m_wrongWords[i].FirstIndex,
                        lastIndex  = m_wrongWords[i].LastIndex
                    },
                    backgroundColor = m_textColorBackWrong,
                    priority        = 3
                });
            }

            // Если курсор находится над каким либо словом
            if (mouseOverWord != null)
            {
                // Подсвечиваем слово, надо которым сейчас курсор

                Color hoverWordColor = m_textColorBackHover;
                if (m_wrongWords.Contains(mouseOverWord))
                {
                    hoverWordColor = m_textColorBackWrongHover;
                }
                else if (m_unselectedPhraseWords.Contains(mouseOverWord))
                {
                    hoverWordColor = m_textColorBackUnselectedPhraseHover;
                }
                else if (m_selectedWords.Contains(mouseOverWord))
                {
                    hoverWordColor = m_textColorBackRightHover;
                }

                selections.Add(new FlowDocumentFormatter.Selection()
                {
                    fontColor  = Colors.Black,
                    fontFamily = this.FontFamily,
                    fontSize   = articleFontSize,
                    range      = new FlowDocumentFormatter.Selection.Range()
                    {
                        firstIndex = mouseOverWord.FirstIndex,
                        lastIndex  = mouseOverWord.LastIndex
                    },
                    backgroundColor = hoverWordColor,
                    priority        = 4
                });

                // Подсвечиваем предложение

                selections.Add(new FlowDocumentFormatter.Selection()
                {
                    fontColor  = Colors.Black,
                    fontFamily = this.FontFamily,
                    fontSize   = articleFontSize,
                    range      = new FlowDocumentFormatter.Selection.Range()
                    {
                        firstIndex = mouseOverWord.Sentence.FirstIndex,
                        lastIndex  = mouseOverWord.Sentence.LastIndex
                    },
                    backgroundColor = m_textColorBackSentence,
                    priority        = 1
                });
            }

            FlowDocumentFormatter.SetTextVisualSelections(m_articleParagraph, selections);
        }