/// <summary> /// Used to set datasource if the control is to display a set of sequences. For example parsed output of a FastA file. /// </summary> /// <param name="sourceList">List of sequences</param> public void SetDataSource(IList <ISequence> sourceList) { this.sequenceList = sourceList; this.sequencePropertiesList = null; this.referenceSequence = null; this.referenceSequenceLine = null; DataSourceUpdated(); }
/// <summary> /// Calculates different measures needed for drawing the panel /// </summary> /// <param name="availableSize">Available size for this panel</param> /// <returns>Total required size, always returns available size back.</returns> protected override Size MeasureOverride(Size availableSize) { if (availableSize.Width <= 0 || availableSize.Height <= 0) { return(new Size(0, 0)); } if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { return(new Size(100, 30)); } if (sequenceList == null || sequenceList.Count == 0 || FontSize < 2) { Children.Clear(); TextBlock noSequencePresentText = new TextBlock(); if (FontSize < 2) { noSequencePresentText.Text = Properties.Resource.SequencesPanel_FontSizeLow; } else { noSequencePresentText.Text = Properties.Resource.SequencesPanel_NothingToDisplay; } noSequencePresentText.Foreground = Brushes.Gainsboro; Children.Add(noSequencePresentText); noSequencePresentText.Measure(availableSize); return(noSequencePresentText.DesiredSize); } // Calculate font dimensions TextBlock charSizeBlock = new TextBlock { FontSize = FontSize }; Children.Add(charSizeBlock); charSizeBlock.Text = "Wp"; charSizeBlock.Measure(availableSize); CharHeight = (int)charSizeBlock.DesiredSize.Height; // Height charSizeBlock.Text = "W"; charSizeBlock.Measure(availableSize); CharWidth = (int)charSizeBlock.DesiredSize.Width + 2; // Width Children.Clear(); displayedSequences.Clear(); gridLines.Clear(); paddingTop = 0; // Calculate display start and end index DisplayEndIndex = ((int)Math.Floor(availableSize.Width / CharWidth)) + DisplayStartIndex; // Add grid Line gridLine; for (int i = 0; i < availableSize.Width; i += (int)CharWidth) { gridLine = new Line(); gridLine.UseLayoutRounding = true; gridLine.X1 = 0; gridLine.X2 = 0; gridLine.Y1 = 0; gridLine.Y2 = availableSize.Height; gridLine.Height = availableSize.Height; gridLine.StrokeThickness = gridLineWidth; gridLine.Width = gridLineWidth; gridLine.Stroke = Brushes.Gainsboro; gridLines.Add(gridLine); Children.Add(gridLine); gridLine.Measure(availableSize); } // Add scale values and grid lines StackPanel scaleValuesPanel = new StackPanel(); scaleValuesPanel.Orientation = Orientation.Horizontal; TextBlock scaleValue; int scaleValueText = DisplayStartIndex; for (int i = 0; i <= availableSize.Width; i += (int)(CharWidth * 10), scaleValueText += 10) { scaleValue = new TextBlock(); scaleValue.FontSize = FontSize; scaleValue.Text = scaleValueText.ToString(); scaleValue.ToolTip = scaleValueText.ToString(); scaleValue.Width = (int)(CharWidth * 10); scaleValuesPanel.Children.Add(scaleValue); } scaleValuesContainer = new Border(); scaleValuesContainer.BorderThickness = new Thickness(0, 0, 0, 2); scaleValuesContainer.BorderBrush = Brushes.Gray; scaleValuesContainer.Child = scaleValuesPanel; scaleValuesContainer.Margin = new Thickness(0, 5, 0, 5); Children.Add(scaleValuesContainer); scaleValuesContainer.Measure(availableSize); paddingTop += scaleValuesContainer.DesiredSize.Height; // Add reference sequence to the panel if (referenceSequence != null) { referenceSequenceLine = new SequenceLine(referenceSequence, this); referenceSequenceLine.IsReferenceSequence = true; referenceSequenceLine.FontSize = FontSize; referenceSequenceLine.Margin = new Thickness(0, 0, 0, 10); Children.Add(referenceSequenceLine); referenceSequenceLine.Measure(availableSize); paddingTop += referenceSequenceLine.DesiredSize.Height; } // Calculate max number of items displayable on screen SequenceLine newSeq = new SequenceLine(sequenceList[0], this); newSeq.Measure(availableSize); MaxVisibleItemCount = Math.Max(0, ((int)Math.Floor((availableSize.Height - paddingTop) / newSeq.DesiredSize.Height))); // -1 else last sequence might be cut off partly coz of rounding issues MaxVisibleCharCount = Math.Max(0, (int)Math.Floor(availableSize.Width / CharWidth)); // Add sequences for (int currentSourceIndex = SourceStartIndex; (currentSourceIndex < SourceStartIndex + MaxVisibleItemCount + 1) && sequenceList.Count > currentSourceIndex; currentSourceIndex++) { ISequence sequenceToAssign = sequenceList[currentSourceIndex]; if (sequencePropertiesList != null) { if (sequencePropertiesList[currentSourceIndex].IsComplemented && sequencePropertiesList[currentSourceIndex].IsReversed) { sequenceToAssign = sequenceToAssign.GetReverseComplementedSequence(); } else if (sequencePropertiesList[currentSourceIndex].IsComplemented) { sequenceToAssign = sequenceToAssign.GetComplementedSequence(); } else if (sequencePropertiesList[currentSourceIndex].IsReversed) { sequenceToAssign = sequenceToAssign.GetReversedSequence(); } } newSeq = new SequenceLine(sequenceToAssign, this); newSeq.ActualSequenceInside = sequenceList[currentSourceIndex]; // keep reference to the original sequence if (newSeq.ActualSequenceInside == highlightedSequence) { newSeq.SequenceItemsHighlight.Visibility = System.Windows.Visibility.Visible; } else { newSeq.SequenceItemsHighlight.Visibility = System.Windows.Visibility.Hidden; } newSeq.FontSize = FontSize; if (sequencePropertiesList != null) { if (sequencePropertiesList[currentSourceIndex].IsAlignment) { newSeq.AlignStartIndex = 0; newSeq.AlignmentLength = sequenceToAssign.Count; } else { newSeq.AlignStartIndex = sequencePropertiesList[currentSourceIndex].AlignPosition; newSeq.AlignmentLength = sequencePropertiesList[currentSourceIndex].AlignmentLength; } newSeq.ReadAlignStartIndex = sequencePropertiesList[currentSourceIndex].ReadStartAlignPosition; newSeq.IsComplemented = sequencePropertiesList[currentSourceIndex].IsComplemented; newSeq.IsReversed = sequencePropertiesList[currentSourceIndex].IsReversed; } if (sequencePropertiesList != null && sequencePropertiesList[currentSourceIndex].IsAlignment) { // +1 for align start as we need to display 1 based index newSeq.ToolTip = sequenceToAssign.ID + Environment.NewLine + Properties.Resource.StartOffset + " : " + (sequencePropertiesList[currentSourceIndex].AlignPosition + 1) + Environment.NewLine + Properties.Resource.EndOffset + " : " + sequencePropertiesList[currentSourceIndex].AlignmentLength; } else { newSeq.ToolTip = sequenceToAssign.ID; } Children.Add(newSeq); newSeq.Measure(availableSize); displayedSequences.Add(newSeq); } return(availableSize); }