Dynamically switching icons in document to text

4 posts, 0 answers
  1. Chris
    Chris avatar
    12 posts
    Member since:
    Sep 2012

    Posted 12 Jan 2011 Link to this post

    I have a requirement where I need to switch an icon that I have inserted using the inlineuicontainer to text. Currently a user inserts what we are calling a note. An icon is inserted at the cursor position to show that there is a note at this position. Mousing over this icon displays the notes value. Now what I am trying to do is to have a button that would toggle every note that is in the document to hide the inlineiocontainer and to show the notes text value. I currently have this working but the text is not showing up where I would expect it to. I seem to be doing something wrong with the position because I can set the position when the note is inserted and then when I call ShowText the position is changed and it inserts everything in one location.

    public void InsertAnnotation(string GUID, String noteText)
            {
                string url = "/Telerik.Windows.Controls.RichTextBoxUI;component/Images/MSOffice/16/FindNextSpellingError.png";
      
                Image annotationIcon = new Image();
                annotationIcon.Source = new BitmapImage(new Uri(url, UriKind.RelativeOrAbsolute));
      
                CustomHyperLinkButton link = new CustomHyperLinkButton { Width = 20, Height = 20, Content = annotationIcon, Name = "Note_" + GUID,  NoteContent = noteText, };
      
                DocumentPosition position = new DocumentPosition(editor.Document);
      
                position = editor.Document.CaretPosition;
      
                link.LocationInDoc = position;
      
                link.showingText = false;
      
                TextBox textBox = new TextBox { Width = 295, Height = 345, Text = noteText, TextWrapping = TextWrapping.Wrap};
      
                RadWindow radWindow = new RadWindow {Width = 300, Height = 300, Header = "Note", Content = textBox, Visibility = Visibility.Visible };
      
                ToolTipService.SetToolTip(link, radWindow);
      
                link.Click += AnnotationLinkButton_Click;
      
                InlineUIContainer container = new InlineUIContainer
                                                  {
                                                      UiElement = link,
                                                      Width = 20,
                                                      Height = 20d,
                                                  };
      
                editor.InsertInline(container);
      
                position.Reset();
            }
      
    private void ShowText(object sender, RoutedEventArgs e)
            {
                List<InlineUIContainer> links = editor.Document.EnumerateChildrenOfType<InlineUIContainer>().ToList();
      
                foreach (var inlineUiContainer in links)
                {
                    CustomHyperLinkButton btn = (CustomHyperLinkButton) inlineUiContainer.UiElement;
      
                    if (!btn.showingText)
                    {
                        btn.Visibility = Visibility.Collapsed;
      
                        Span span = new Span("{ " + btn.NoteContent + " }");
      
                        editor.Document.InsertInline(span, btn.LocationInDoc);
      
                        btn.showingText = true;
                    }
                }
            }
  2. Iva Toteva
    Admin
    Iva Toteva avatar
    1319 posts

    Posted 13 Jan 2011 Link to this post

    Hello Chris,

    Currently RadRichTextBox does not fully support your scenario. We will take it into consideration in the future, but as of now, a little modification of your code solves the issues you have encountered:

    public void InsertAnnotation(String noteText)
    {
        string url = "/Telerik.Windows.Controls.RichTextBoxUI;component/Images/MSOffice/16/FindNextSpellingError.png";
        Image annotationIcon = new Image();
        annotationIcon.Source = new BitmapImage(new Uri(url, UriKind.RelativeOrAbsolute));
        CustomHyperLinkButton link = new CustomHyperLinkButton { Width = 20, Height = 20, Content = annotationIcon, NoteContent = noteText, };
        link.Click += ShowText;
        InlineUIContainer container = new InlineUIContainer
        {
            UiElement = link,
            Width = 20,
            Height = 20d,
        };
        editor.InsertInline(container);
    }
     
    private void ShowText(object sender, RoutedEventArgs e)
    {
        CustomHyperLinkButton pressedButton = sender as CustomHyperLinkButton;
        List<InlineUIContainer> links = editor.Document.EnumerateChildrenOfType<InlineUIContainer>().ToList();
        foreach (var container in links)
        {
            CustomHyperLinkButton btn = container.UiElement as CustomHyperLinkButton;
            if (btn == pressedButton )
            {
                Span span = new Span("{ " + btn.NoteContent + " }");
                var inlineBox = container.FirstLayoutBox as InlineLayoutBox;
                if (inlineBox != null)
                {
                    editor.Document.CaretPosition.MoveToInline(inlineBox, 0);
                    editor.Document.InsertInline(span);                   
                }
                editor.Document.CaretPosition.MoveToNextSpanBox();
                btn.Visibility = Visibility.Collapsed;
                container.Height = 0;
                container.Width = 0;
           //   this.editor.Delete(true); //if you want to delete the InlineUIContainer with the button
            }
            this.editor.UpdateEditorLayout(); //this is needed only if you set the container.Height and Width properties
        }
    }

    Note that DocumentPosition is a reference type and 
    position = editor.Document.CaretPosition;
    creates an alias for the CaretPosition and it changes when the caret position moves. What you need most probably is:
    position = new DocumentPosition(editor.Document.CaretPosition);

    Saving the DocumentPosition when creating the CustomHyperLinkButton is also a tricky moment, as this DocumentPosition will not be anchored to the same position in the document when the document content changes.
    Try this approach and let us know if this solution does not match your requirements or you experience any further difficulties.

    All the best,
    Iva
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
  3. Chris
    Chris avatar
    12 posts
    Member since:
    Sep 2012

    Posted 13 Jan 2011 Link to this post

    Thank you for your help with this. This was a lot of help. I will share what I came up with as my solution to the problem. It is pretty much code for annotating a document. Let me know if you see anyway to improve upon it.

    private void ToggleCommentView(object sender, RoutedEventArgs e)
            {
                List<InlineUIContainer> links = editor.Document.EnumerateChildrenOfType<InlineUIContainer>().ToList();
      
                List<Paragraph> paragraphs = editor.Document.EnumerateChildrenOfType<Paragraph>().ToList();
      
                List<Span> spans = editor.Document.EnumerateChildrenOfType<Span>().ToList();
      
                if (!ShowingComments)
                {
                    foreach (var inlineUiContainer in links)
                    {
                        CustomHyperLinkButton btn = (CustomHyperLinkButton) inlineUiContainer.UiElement;
      
                        if (btn.AnnotationType == Constants.AnnotationTypes.AnnotationType.Comment)
                        {
                            Span span = new Span("[ " + btn.CommentContent + " ]")
                                            {
                                                ForeColor = Colors.Red,
                                                FontStyle = FontStyles.Italic,
                                                FontSize = 10
                                            };
                            var inlineBox = inlineUiContainer.FirstLayoutBox as InlineLayoutBox;
                            if (inlineBox != null)
                            {
                                editor.Document.CaretPosition.MoveToInline(inlineBox, 0);
                                editor.Document.InsertInline(span);
                            }
                            editor.Document.CaretPosition.MoveToNextSpanBox();
                            btn.Visibility = Visibility.Collapsed;
                            inlineUiContainer.Height = 0;
                            inlineUiContainer.Width = 0;
                        }
                    }
      
                    this.editor.UpdateEditorLayout();
                    ShowingComments = true;
                }
                else
                {
                    foreach (var inlineUiContainer in links)
                    {
                        CustomHyperLinkButton btn = (CustomHyperLinkButton) inlineUiContainer.UiElement;
      
                        editor.Document.CaretPosition.MoveToNextSpanBox();
                        btn.Visibility = Visibility.Visible;
                        inlineUiContainer.Height = 20;
                        inlineUiContainer.Width = 20d;
      
                        foreach (var paragraph in paragraphs)
                        {
                            foreach (var span in spans)
                            {
                                if (span.Text == "[ " + btn.CommentContent + " ]")
                                    paragraph.Inlines.Remove(span);
                            }
                        }
                    }
      
                    this.editor.UpdateEditorLayout();
                    ShowingComments = false;
                }
            }
  4. Iva Toteva
    Admin
    Iva Toteva avatar
    1319 posts

    Posted 18 Jan 2011 Link to this post

    Hello Chris,
    Your code looks OK to me with just a few remarks.
    1. When you are removing the span and substituting it for the button, you are making some unneeded operations (trying to remove a span from all paragraphs, instead of its own only). The following optimization can be applied:
    2. else
      {
          foreach (var inlineUiContainer in links)
          {
              CustomHyperLinkButton btn = (CustomHyperLinkButton)inlineUiContainer.UiElement;
              editor.Document.CaretPosition.MoveToNextSpanBox();
              btn.Visibility = Visibility.Visible;
              inlineUiContainer.Height = 20;
              inlineUiContainer.Width = 20;
       
              Paragraph paragraph = inlineUiContainer.Parent as Paragraph;
              foreach (var span in paragraph.EnumerateChildrenOfType<Span>())
              {
                  if (span.Text == "[ " + btn.ActualHeight + " ]")
                  {
                      paragraph.Inlines.Remove(span);
                  }
              }
          }
          this.editor.UpdateEditorLayout();
          ShowingComments = false;
      }
    3.  If you are not using RadRichTextBox in read only mode, you might encounter unexpected behavior. Copy-pasting of InlineUIContainers will not work properly, as you cannot add one and the same button two times in the same document (both when the button is visible and collapsed).
    If you have other questions, do not hesitate to contact us again.

    Regards,
    Iva
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
Back to Top