/// <summary> /// Choose an IAnnotationComponent for a given IAttachedAnnotation. Implementation in AnnotationComponentChooser knows /// about all out-of-box IAnnotationComponents. The default mapping will be stated here later. /// Subclasses can overwrite this method to return application specific mapping. /// Note: In future release this method should be made virtual. /// </summary> /// <param name="attachedAnnotation">The IAttachedAnnotation that needs an IAnnotationComponent </param> /// <returns></returns> public IAnnotationComponent ChooseAnnotationComponent(IAttachedAnnotation attachedAnnotation) { if (attachedAnnotation == null) throw new ArgumentNullException("attachedAnnotation"); IAnnotationComponent ac = null; // Text StickyNote if (attachedAnnotation.Annotation.AnnotationType == StickyNoteControl.TextSchemaName) { ac = new StickyNoteControl(StickyNoteType.Text) as IAnnotationComponent; } // Ink StickyNote else if (attachedAnnotation.Annotation.AnnotationType == StickyNoteControl.InkSchemaName) { ac = new StickyNoteControl(StickyNoteType.Ink) as IAnnotationComponent; } // Highlight else if (attachedAnnotation.Annotation.AnnotationType == HighlightComponent.TypeName) { ac = new HighlightComponent() as IAnnotationComponent; } return ac; }
/// <summary> /// Update the metadata tokens specified in token. /// </summary> private static void UpdateMetaData(XmlToken token, StickyNoteControl snc, SNCAnnotation sncAnnotation) { bool newCargo, newRoot; AnnotationResource cargo; XmlElement root; GetCargoAndRoot(sncAnnotation, XmlToken.MetaData, out cargo, out root, out newCargo, out newRoot); // Update Expanded if ((token & XmlToken.IsExpanded) != 0) { bool expanded = snc.IsExpanded; sncAnnotation.UpdateAttribute(root, XmlToken.IsExpanded, expanded.ToString(CultureInfo.InvariantCulture)); } // Update Height if ((token & XmlToken.Height) != 0) { Debug.Assert(snc.IsExpanded); double height = (double)snc.GetValue(FrameworkElement.HeightProperty); sncAnnotation.UpdateAttribute(root, XmlToken.Height, height.ToString(CultureInfo.InvariantCulture)); } // Update Width if ((token & XmlToken.Width) != 0) { Debug.Assert(snc.IsExpanded); double width = (double)snc.GetValue(FrameworkElement.WidthProperty); sncAnnotation.UpdateAttribute(root, XmlToken.Width, width.ToString(CultureInfo.InvariantCulture)); } // Update Left if ((token & XmlToken.Left) != 0) { double left = snc.PositionTransform.X; // All 'left' values are persisted assuming two things: // 1) the top-left corner (visually) of the StickyNote is the origin of its coordinate space // 2) the positive x-axis of its parent is to the right // This flag signals that we have a positive x-axis to the left and our // top-right corner (visually) is our origin. So we need to flip the // value before persisting it. if (snc.FlipBothOrigins) { left = -(left + snc.Width); } sncAnnotation.UpdateAttribute(root, XmlToken.Left, left.ToString(CultureInfo.InvariantCulture)); } // Update Top if ((token & XmlToken.Top) != 0) { sncAnnotation.UpdateAttribute(root, XmlToken.Top, snc.PositionTransform.Y.ToString(CultureInfo.InvariantCulture)); } // Update XOffset if ((token & XmlToken.XOffset) != 0) { sncAnnotation.UpdateAttribute(root, XmlToken.XOffset, snc.XOffset.ToString(CultureInfo.InvariantCulture)); } // Update YOffset if ((token & XmlToken.YOffset) != 0) { sncAnnotation.UpdateAttribute(root, XmlToken.YOffset, snc.YOffset.ToString(CultureInfo.InvariantCulture)); } // Update ZOrder if ((token & XmlToken.ZOrder) != 0) { sncAnnotation.UpdateAttribute(root, XmlToken.ZOrder, ((IAnnotationComponent)snc).ZOrder.ToString(CultureInfo.InvariantCulture)); } if (newRoot) { cargo.Contents.Add(root); } if (newCargo) { sncAnnotation._annotation.Cargos.Add(cargo); } }
/// <summary> /// This static method will update a StickyNoteControl object with the specified data in an Annotation /// </summary> /// <param name="token">A flag which indicates the data needs to be updated. The flag can be combinated with the any valid bits.</param> /// <param name="snc">A StickyNoteControl instance</param> /// <param name="sncAnnotation">An SNCAnnotation object which contains a CAF annotation object</param> public static void UpdateStickyNoteControl(XmlToken token, StickyNoteControl snc, SNCAnnotation sncAnnotation) { Invariant.Assert((token & AllValues) != 0, "No token specified."); Invariant.Assert(snc != null, "Sticky Note Control is null."); Invariant.Assert(sncAnnotation != null, "Annotation is null."); // XmlAttribute node; // Update Ink if ((token & XmlToken.Ink) != 0 && sncAnnotation.HasInkData) { sncAnnotation.UpdateContent(snc, false, XmlToken.Ink); } // Update Text if ((token & XmlToken.Text) != 0 && sncAnnotation.HasTextData) { sncAnnotation.UpdateContent(snc, false, XmlToken.Text); } // Update Author if ((token & XmlToken.Author) != 0) { int nCount = sncAnnotation._annotation.Authors.Count; // Get the culture specific text separator. string listSeparator = snc.Language.GetSpecificCulture().TextInfo.ListSeparator; string authors = string.Empty; for (int i = 0; i < nCount; i++) { if (i != 0) { authors += listSeparator + sncAnnotation._annotation.Authors[i]; } else { authors += sncAnnotation._annotation.Authors[i]; } } // Setting the author property will cause the UI to update snc.SetValue(StickyNoteControl.AuthorPropertyKey, authors); } // Update Height if ((token & XmlToken.Height) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.Height); if (node != null) { double height = Convert.ToDouble(node.Value, CultureInfo.InvariantCulture); snc.SetValue(FrameworkElement.HeightProperty, height); } else { snc.ClearValue(FrameworkElement.HeightProperty); } } // Update Width if ((token & XmlToken.Width) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.Width); if (node != null) { double width = Convert.ToDouble(node.Value, CultureInfo.InvariantCulture); snc.SetValue(FrameworkElement.WidthProperty, width); } else { snc.ClearValue(FrameworkElement.WidthProperty); } } // Update IsExpanded if ((token & XmlToken.IsExpanded) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.IsExpanded); if (node != null) { bool expanded = Convert.ToBoolean(node.Value, CultureInfo.InvariantCulture); snc.IsExpanded = expanded; } else { snc.ClearValue(StickyNoteControl.IsExpandedProperty); } } // Update ZOrder if ((token & XmlToken.ZOrder) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.ZOrder); if (node != null) { ((IAnnotationComponent)snc).ZOrder = Convert.ToInt32(node.Value, CultureInfo.InvariantCulture); } } // Update Position if ((token & PositionValues) != 0) { TranslateTransform transform = new TranslateTransform(); if ((token & XmlToken.Left) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.Left); if (node != null) { double left = Convert.ToDouble(node.Value, CultureInfo.InvariantCulture); // All 'left' values are persisted assuming two things: // 1) the top-left corner (visually) of the StickyNote is the origin of its coordinate space // 2) the positive x-axis of its parent is to the right // This flag signals that we have a positive x-axis to the left and our // top-right corner (visually) is our origin. So we need to flip the // value before using it. if (snc.FlipBothOrigins) { left = -(left + snc.Width); } transform.X = left; } } if ((token & XmlToken.Top) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.Top); if (node != null) { double top = Convert.ToDouble(node.Value, CultureInfo.InvariantCulture); transform.Y = top; } } // Now, we update the StickyNote offset if ((token & XmlToken.XOffset) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.XOffset); if (node != null) { snc.XOffset = Convert.ToDouble(node.Value, CultureInfo.InvariantCulture); } } if ((token & XmlToken.YOffset) != 0) { node = (XmlAttribute)sncAnnotation.FindData(XmlToken.YOffset); if (node != null) { snc.YOffset = Convert.ToDouble(node.Value, CultureInfo.InvariantCulture); } } // Set the adorner layer transform. snc.PositionTransform = transform; } }
// Update ink data from/to SNC. private void UpdateContent(StickyNoteControl snc, bool updateAnnotation, XmlToken token) { Invariant.Assert(snc != null, "Sticky Note Control is null."); Invariant.Assert((token & AllContents) != 0, "No token specified."); StickyNoteContentControl contentControl = snc.Content; // Template hasn't been applied yet. Once it has the content control will then be setup. if (contentControl == null) { return; } // Check whether the annotation data matches the content control. if ((token == XmlToken.Ink && contentControl.Type != StickyNoteType.Ink) || (token == XmlToken.Text && contentControl.Type != StickyNoteType.Text)) { Debug.Assert(false, "The annotation data does match with the current content control in StickyNote"); return; } XmlElement root = null; if (updateAnnotation) { // Update annotation from SNC AnnotationResource cargo = null; bool newRoot = false; bool newCargo = false; // Check if the text is empty. if (!contentControl.IsEmpty) { GetCargoAndRoot(this, token, out cargo, out root, out newCargo, out newRoot); contentControl.Save(root); } else { string cargoName = GetCargoName(token); cargo = FindCargo(cargoName); if (cargo != null) { _annotation.Cargos.Remove(cargo); _cachedXmlElements.Remove(token); } } if (newRoot) { Invariant.Assert(root != null, "XmlElement should have been created."); Invariant.Assert(cargo != null, "Cargo should have been retrieved."); cargo.Contents.Add(root); } if (newCargo) { Invariant.Assert(cargo != null, "Cargo should have been created."); _annotation.Cargos.Add(cargo); } } else { // Update SNC from annotation // Check if we have the text data in the xml store. XmlElement node = (XmlElement)FindData(token); if (node != null) { contentControl.Load(node); } else { if (!contentControl.IsEmpty) { contentControl.Clear(); } } } }
//------------------------------------------------------------------------------- // // Public Methods // //------------------------------------------------------------------------------- #region Public Methods /// <summary> /// This static method will update an Annotation object with the specified data in a StickyNoteControl /// </summary> /// <param name="token">A flag which indicates the data needs to be updated. The flag can be combinated with the any valid bits.</param> /// <param name="snc">A StickyNoteControl instance</param> /// <param name="sncAnnotation">An SNCAnnotation object which contains a CAF annotation object</param> public static void UpdateAnnotation(XmlToken token, StickyNoteControl snc, SNCAnnotation sncAnnotation) { AnnotationService service = null; bool autoFlush = false; try { service = AnnotationService.GetService(((IAnnotationComponent)snc).AnnotatedElement); if (service != null && service.Store != null) { autoFlush = service.Store.AutoFlush; // Temporarily turn off autoflush until we are done // updating all the necessary values service.Store.AutoFlush = false; } Debug.Assert((token & AllValues) != 0); // Update Ink if ((token & XmlToken.Ink) != 0 && snc.Content.Type == StickyNoteType.Ink) { sncAnnotation.UpdateContent(snc, true, XmlToken.Ink); } // Update Text if ((token & XmlToken.Text) != 0 && snc.Content.Type == StickyNoteType.Text) { sncAnnotation.UpdateContent(snc, true, XmlToken.Text); } // Update MetaData if ((token & NegativeAllContents) != 0) { UpdateMetaData(token, snc, sncAnnotation); } } finally { if (service != null && service.Store != null) { // If auto flush was true before, setting it to true again should cause a flush. service.Store.AutoFlush = autoFlush; } } }