source: trunk/Obi/Obi/ProjectView/Strip.cs @ 7625

Revision 7625, 83.2 KB checked in by rohit_tandon, 4 months ago (diff)

-> Comment will now save. Undo Redo will also work now.

Line 
1using System;
2using System.ComponentModel;
3using System.Drawing;
4using System.Windows.Forms;
5using System.Threading;
6using System.Collections.Generic ;
7
8namespace Obi.ProjectView
9{
10    public partial class Strip : UserControl, ISearchable, ISelectableInContentViewWithColors
11    {
12        private float mAudioScale;           // local audio scale for the strip
13        private int mBlockLayoutBaseHeight;  // base height of the block layout (for zooming)
14        private int mBlockHeight;            // height of a single line of the block layout
15        private ContentView mContentView;    // parent content view
16        private bool mHighlighted;           // highlighted flag (when the section node is selected)
17        private Mutex mLabelUpdateThread;    // thread to update labels
18        private SectionNode mNode;           // the section node for this strip
19        private bool mWrap;                  // wrap contents
20        private bool m_IsBlocksVisibilityProcessActive; // @phraseLimit
21        private int m_OffsetForFirstPhrase = 0;//@singleSection
22        private Rectangle m_ScreenResolution; // Stores screen resolution @ScreenResolution
23
24        private StripCursor m_AnimationCursor;// @zoomwaveform
25        private StripCursor m_TempCursor;// @zoomwaveform
26        private Block m_PrevRecBlock; // Stores previous recording Block. It is used for removing color of previous recording phrase.
27        private const int m_BaseScreenResolution = 768; //@ScreenResolution
28        private EditableLabel m_EditableLabel;
29        private EmptyNode m_SelectedNodeToAddComment;
30        private double m_TimeOfCursor;
31        /// <summary>
32        /// This constructor is used by the designer.
33        /// </summary>
34        public Strip()
35        {
36            InitializeComponent();
37            this.Disposed += new EventHandler(Strip_Disposed);
38            m_ScreenResolution = Screen.PrimaryScreen.Bounds;
39            mBlockLayoutBaseHeight = mBlockLayout.Height;
40            mBlockHeight = 0;
41            mLabel.Editable = false;
42            mNode = null;
43            Highlighted = false;
44            mWrap = false;
45            mLabelUpdateThread = new Mutex();
46            m_IsBlocksVisibilityProcessActive = false; // @phraseLimit
47        }
48
49        /// <summary>
50        /// Create a new strip with an associated section node.
51        /// </summary>
52        public Strip(SectionNode node, ContentView parent)
53            : this()
54        {
55            if (node == null) throw new Exception("Cannot set a null section node for a strip!");
56            mNode = node;
57            Label = mNode.Label;
58            mContentView = parent;
59            if (mContentView.Settings.Project_IncreasePhraseHightForHigherResolution && m_ScreenResolution.Height > m_BaseScreenResolution) //@ScreenResolution
60            {
61                float heightRatio = (float)Screen.PrimaryScreen.Bounds.Height / m_BaseScreenResolution; 
62                mBlockLayoutBaseHeight = (int)(mBlockLayout.Height * heightRatio);
63            }
64            mContentView.SizeChanged += new EventHandler(Resize_View);
65            ZoomFactor = mContentView.ZoomFactor;
66            AudioScale = mContentView.AudioScale;
67            UpdateColors();
68            SetAccessibleName();
69            if (mContentView.Settings.ObiFont != this.Font.Name) //@fontconfig
70            {
71                mLabel.SetFont(mContentView.Settings); //@fontconfig
72            }
73        }
74
75
76        /// <summary>
77        /// Get or set the audio scale for *this* strip (may differ from the parent's.)
78        /// </summary>
79        public float AudioScale
80        {
81            get { return mAudioScale; }
82            set
83            {
84                if (value > 0.0)
85                {
86                    mAudioScale = value;
87                    foreach (Control c in mBlockLayout.Controls) if (c is AudioBlock) ((AudioBlock)c).AudioScale = value;
88                    Resize_Blocks();
89                    mContentView.UpdateSize ();
90                    mContentView.EnsureVisibilityOfSelectedItem();
91                }
92            }
93        }
94
95        /// <summary>
96        /// Get or set the color settings from the content view.
97        /// </summary>
98        public ColorSettings ColorSettings
99        {
100            get { return mContentView == null ? null : mContentView.ColorSettings; }
101            set { UpdateColors(value); }
102        }
103
104
105// @phraseLimit
106        /// <summary>
107        /// returns true if all the blocks in strip are visible
108                /// </summary>
109        public bool IsBlocksVisible
110            {
111            get
112                {
113                if (mNode.PhraseChildCount == 0)
114                    return true;
115                else if (mBlockLayout.Controls.Count < (mNode.PhraseChildCount * 2 ) + 1 )
116                    return false;
117                else
118                    return true;
119                }
120            }
121        // @phraseLimit
122        public bool IsBlocksVisibilityProcessActive
123            {
124             get { return m_IsBlocksVisibilityProcessActive ; }
125            set { m_IsBlocksVisibilityProcessActive = value ;}
126            }
127
128
129        /// <summary>
130        /// Get the content view for the strip.
131        /// </summary>
132        public ContentView ContentView { get { return mContentView; } }
133
134        /// <summary>
135        /// <Empty node in which recording is going on
136        /// </summary>
137        public EmptyNode RecordingNode { get { return mContentView != null ? mContentView.RecordingNode: null; } }
138        /// <summary>
139        /// Get the first block in the strip, or null if empty.
140        /// </summary>
141        public Block FirstBlock
142        {
143            get { return mBlockLayout.Controls.Count > 1 ? mBlockLayout.Controls[1] as Block : null; }
144        }
145
146        /// <summary>
147        /// Get or set the highlighted flag for the strip corresponding to the section node being (de)selected.
148        /// </summary>
149        public bool Highlighted
150        {
151            get { return mHighlighted; }
152            set
153            {
154                mHighlighted = value && !(mContentView.Selection is TextSelection);
155                if (mHighlighted && mLabel.Editable) mLabel.Editable = false;
156                UpdateColors();
157                if (mHighlighted) UpdateWaveforms(AudioBlock.STRIP_SELECTED_PRIORITY);
158            }
159        }
160
161        /// <summary>
162        /// Get or set the label of the strip where the title of the section can be edited.
163        /// </summary>
164        public string Label
165        {
166            get { return mLabel.Label; }
167            set
168            {
169                if (value != null && value != "")
170                {
171                    mLabel.Label = value;
172                    SetAccessibleName();
173                }
174                Resize_Label();
175            }
176        }
177
178        /// <summary>
179        /// Get the last block in the strip, or null if empty.
180        /// </summary>
181        public Block LastBlock
182        {
183            get
184            {
185                return mBlockLayout.Controls.Count > 1 ? mBlockLayout.Controls[mBlockLayout.Controls.Count - 2] as Block :
186                    null;
187            }
188        }
189
190        /// <summary>
191        /// Get the tab index of the last block in the strip.
192        /// Strip cursors are skipped when tabbing.
193        /// </summary>
194        public int LastTabIndex
195        {
196            get
197            {
198                int last = mBlockLayout.Controls.Count - 2;
199                return last >= 0 ? ((Block)mBlockLayout.Controls[last]).LastTabIndex : TabIndex;
200            }
201        }
202
203        /// <summary>
204        /// Get the section node for this strip.
205        /// </summary>
206        public SectionNode Node { get { return mNode; } }
207
208        /// <summary>
209        /// Get the (generic) node for this strip; used for selection.
210        /// </summary>
211        public ObiNode ObiNode { get { return mNode; } }
212
213        /// <summary>
214        /// Get the current selection for this node (i.e. the strip, its label or an index is selected.)
215        /// </summary>
216        public NodeSelection Selection
217        {
218            get
219            {
220                NodeSelection selection = mContentView == null ? null : mContentView.Selection;
221                return selection == null || selection.Node != mNode ? null : selection;
222            }
223        }
224
225        /// <summary>
226        /// Set the wrap parameter.
227        /// </summary>
228        public bool WrapContents
229        {
230            set
231            {
232                mWrap = value;
233                Resize_Wrap();
234            }
235        }
236
237        //@singleSection
238        public bool IsContentViewFilledWithBlocks
239            {
240            get
241                {
242                int stripsPanelLocation = this.Parent != null ? this.Parent.Location.Y : 0;
243                if (mBlockLayout != null && mBlockLayout.Controls.Count > 0
244                    && (mBlockLayout.Controls[mBlockLayout.Controls.Count - 1].Location.Y + stripsPanelLocation) > mContentView.ContentViewDepthForCreatingBlocks)
245                    {
246                    //Console.WriteLine ( mBlockLayout.Controls[mBlockLayout.Controls.Count - 1].Location.Y + .Y );
247                    return true;
248                    }
249                else
250                    {
251                    return false;
252                    }
253                }
254            }
255
256        //@singleSection
257        public int OffsetForFirstPhrase
258            {
259            get
260                {
261                int offsetIndex_FirstPhrase = m_OffsetForFirstPhrase;
262                if (mBlockLayout.Controls.Count > 1)
263                    {
264                    Control c = mBlockLayout.Controls[1];
265                    if (c is Block)
266                        {
267                        offsetIndex_FirstPhrase = ((Block)c).Node.Index;
268                        }
269                    }
270                return m_OffsetForFirstPhrase = offsetIndex_FirstPhrase;
271                }
272            }
273
274//@singleSection
275        public int BlocksLayoutTopPosition
276            {
277            get
278                {
279                //Console.WriteLine ( "blocks layout upper y : " + mBlockLayout.Location.Y );
280                return mBlockLayout.Location.Y ;
281                }
282            }
283
284        /// <summary>
285        /// Set the zoom factor for the strip and its contents.
286        /// </summary>
287        public float ZoomFactor
288        {
289            set
290            {
291                if (value > 0.0f)
292                {
293                    mLabel.ZoomFactor = value;
294                    mBlockHeight = (int)Math.Round(value * mBlockLayoutBaseHeight);
295                    foreach (Control c in mBlockLayout.Controls)
296                    {
297                        if (c is Block)
298                        {
299                            ((Block)c).SetZoomFactorAndHeight(value, mBlockHeight);
300                        }
301                        else if (c is StripCursor)
302                        {
303                            ((StripCursor)c).SetHeight(mBlockHeight);
304                        }
305                    }
306                    Resize_Zoom();
307                }
308            }
309        }
310
311    //@singleSection
312    public bool IsContentViewFilledWithBlocksTillPixelDepth ( int pixelDepth )
313        {
314        //Console.WriteLine ( "pixel check : " + mBlockLayout.Controls[mBlockLayout.Controls.Count - 1].Location.Y + " " + this.Parent.Location.Y );
315            if (mBlockLayout != null && mBlockLayout.Controls.Count > 0
316                                     && (mBlockLayout.Controls[mBlockLayout.Controls.Count - 1].Location.Y + mBlockLayout.Location.Y + 
317                                     this.Parent.Location.Y) > pixelDepth)
318                {
319                //Console.WriteLine ( "pixel depth in strip " + pixelDepth );
320                return true;
321                }
322            else
323                {
324                return false;
325                }
326           
327        }
328
329        //@singleSection
330        public List<int> GetBoundaryPhrasesIndexForVisiblePhrases ( int startY, int endY )
331            {
332            List<int> boundaryIndex = new List<int> ();
333           
334            foreach (Control c in mBlockLayout.Controls)
335                {
336                if (c is Block)
337                    {
338                    Block b = (Block)c;
339                    if (b.Location.Y >= startY -10 && boundaryIndex.Count == 0) boundaryIndex.Add ( b.Node.Index );
340
341                    if ( boundaryIndex.Count == 1 && 
342                        ( b.Location.Y > endY || b == LastBlock ))
343                        {
344                        boundaryIndex.Add ( b.Node.Index ) ;
345                        }
346                    }
347                }
348            return boundaryIndex;
349            }
350
351        //@singleSection
352        public int GetPhraseCountForContentViewVisibleHeight ( int visibleHeight,int visibleWidth,  EmptyNode node, bool checkWithFollowingPhrases )
353            {
354            int expectedRows = Convert.ToInt32 ( visibleHeight / (103 * mContentView.ZoomFactor)) + 1 ;
355            int expectedMilliseconds = Convert.ToInt32 ( (visibleWidth / 12) * mContentView.ZoomFactor ) * expectedRows * 1000;
356            // use time for this
357            double time = 0;
358            int phraseCount = 0;
359            double maxAllowedTimePerPhrase = Convert.ToInt32 ( (visibleWidth / 12) * mContentView.ZoomFactor ) * 1000;
360
361            for (int i = node.Index; i >= 0; --i)
362                {
363                double phraseDuration = mNode.PhraseChild ( i ).Duration ;
364                time += phraseDuration < maxAllowedTimePerPhrase ? phraseDuration : maxAllowedTimePerPhrase;
365                phraseCount++;
366
367                if (time > expectedMilliseconds)
368                    {
369                    //Console.WriteLine ( " phrase count for visible page is " + phraseCount );
370                    break;
371                    }
372                }
373
374            return phraseCount;
375            }
376
377        //@singleSection
378        public bool IsBlockForEmptyNodeExists ( EmptyNode node )
379            {
380            if ( mBlockLayout.Controls.Count == 0 ) return false;
381
382            if (node.Index < OffsetForFirstPhrase) return false;
383            //int startIndexForIteration = node.Index - FirstBlock.Node.Index;
384            // in future if first block is not 0 index phrase then it is better to use find block function
385            //int startIndexForIteration = node.Index ;
386            int startIndexForIteration = node.Index- OffsetForFirstPhrase;
387            int blockControlIndex = (startIndexForIteration * 2) + 1;
388
389            if (blockControlIndex >= mBlockLayout.Controls.Count) return false;
390            //Console.WriteLine ( "phrase index " + node.Index + "  first node " + FirstBlock.Node.Index );
391            if (mBlockLayout.Controls[blockControlIndex] is Block
392                && ((Block) mBlockLayout.Controls[blockControlIndex]).Node == node)
393                {
394                //Console.WriteLine ( "IsBlockForEmptyNodeExists true" );
395                return true;
396                }
397            else
398                {
399                //Console.WriteLine ( "IsBlockForEmptyNodeExists is false for : " + node.ToString () );
400                return false ;
401                }
402            }
403
404        //@singleSection
405        public bool IsStripsControlsWithinSafeCount
406        {
407            get
408            {
409                return mBlockLayout.Controls.Count < 1001;
410            }
411        }
412
413
414        private delegate Block BlockInvokation(EmptyNode node);
415
416        /// <summary>
417        /// Add a new block for an empty node. Return the block once added.
418        /// Cursors are added if necessary: one after the block, and one before
419        /// if it is the first block of the strip.
420        /// </summary>
421        public Block AddBlockForNode(EmptyNode node)
422        {
423            if (InvokeRequired)
424            {
425                return (Block)Invoke(new BlockInvokation(AddBlockForNode), node);
426            }
427            else
428            {
429            return CreateBlockForNode ( node, true );
430            }
431        }
432
433        //@singleSection
434        private delegate Block BlockRangeCreationInvokation(EmptyNode startNode,EmptyNode endNode);
435
436        //@singleSection
437        public Block AddsRangeOfBlocks(EmptyNode startNode, EmptyNode endNode)
438        {
439            if (InvokeRequired)
440            {
441                return (Block)Invoke(new BlockRangeCreationInvokation(AddsRangeOfBlocks), startNode, endNode);
442            }
443            else
444                {
445                for (int i = startNode.Index; i <= endNode.Index; ++i)
446                    {
447                    CreateBlockForNode ( mNode.PhraseChild ( i),endNode.Index == i ?  true : false);
448                    }
449                    UpdateColors();
450                return null ;
451                }
452            }
453
454        //@singleSection
455        private Block CreateBlockForNode ( EmptyNode node , bool updateSize)
456            {
457            // first check if blocks count has exceeded handle limit : ( nodes limit * 2 ) +1
458            if ((mBlockLayout.Controls.Count + (m_BackgroundBlockLayout != null ? m_BackgroundBlockLayout.Controls.Count : 0)) > 2001
459                || !IsStripsControlsWithinSafeCount)
460                return null;
461
462
463            if (IsBlockForEmptyNodeExists ( node )) return FindBlock ( node );
464
465            // if node index is just one less than offset of strip and node inserted is 0 node then allow insert else return null
466            if (mBlockLayout.Controls.Count > 1 && OffsetForFirstPhrase - node.Index > 0 && node.Index > 0) return null;
467            // if node index is 0 but offset is not 1 then also return
468            if (node.Index == 0 && OffsetForFirstPhrase > 1 && mBlockLayout.Controls.Count > 0) return null;
469
470            if (mBlockLayout.Controls.Count == 0)
471                {
472                StripCursor cursor = AddCursorAtBlockLayoutIndex ( 0 );
473
474                m_OffsetForFirstPhrase = node.Index;//@singleSection
475                //Console.WriteLine ( "Offset of strip at 0 blocks is " + m_OffsetForFirstPhrase );
476                }
477
478            Block block = node is PhraseNode ? new AudioBlock ( (PhraseNode)node, this, mContentView.Settings.Project_ShowWaveformInContentView ) : new Block ( node, this );
479            if (mBlockLayout.Controls.Count <= 5 && mBlockLayout.Width < mContentView.Width - 50) WrapContents = false; // to make more than 3 phrases visible in merge with empty section.
480            mBlockLayout.Controls.Add ( block );
481            if (m_PrevRecBlock != null && RecordingNode != null)
482            {
483                m_PrevRecBlock.UpdateColors();
484            }
485            m_PrevRecBlock = block; 
486            //@singleSection: following 2 lines replaced
487            //mBlockLayout.Controls.SetChildIndex(block, 1 + 2 * node.Index);
488            //AddCursorAtBlockLayoutIndex(2 + 2 * node.Index);
489             //Console.WriteLine ( "block index to place " + node.Index + " " + OffsetForFirstPhrase );
490            //mBlockLayout.Controls.SetChildIndex ( block, 1 + 2 * (node.Index - OffsetForFirstPhrase) );
491            //AddCursorAtBlockLayoutIndex ( 2 + 2 * (node.Index - OffsetForFirstPhrase) );
492            // adding following 3 lines for replacement of above 2 lines
493            int blockIndexToSet =node.Index == 0 && OffsetForFirstPhrase == 1 ? 1:  1 + 2 * (node.Index - OffsetForFirstPhrase );
494            mBlockLayout.Controls.SetChildIndex(block, blockIndexToSet);
495            AddCursorAtBlockLayoutIndex(blockIndexToSet+1);
496            if (mContentView.Settings.Project_IncreasePhraseHightForHigherResolution && m_ScreenResolution.Height > m_BaseScreenResolution) //@ScreenResolution
497            {
498                float BlockWidthRatio = (float)Screen.PrimaryScreen.Bounds.Height / m_BaseScreenResolution; 
499                block.SetZoomFactorForHigherResolution(mContentView.ZoomFactor, mBlockHeight, BlockWidthRatio);
500            }
501            else
502            {
503                block.SetZoomFactorAndHeight(mContentView.ZoomFactor, mBlockHeight);
504            }
505            block.Cursor = Cursor;
506            block.SizeChanged += new EventHandler ( Block_SizeChanged );
507
508            if ( updateSize )  Resize_Blocks  ();
509
510            //UpdateStripCursorsAccessibleName ( 2 + 2 * node.Index );
511            int blockIndex = mBlockLayout.Controls.IndexOf ( block );
512            UpdateStripCursorsAccessibleName (blockIndex - 1) ;
513            //Console.WriteLine ( "block ref index " + mBlockLayout.Controls.IndexOf ( block ) + " " + (2 + 2 * node.Index) + " offset:" + OffsetForFirstPhrase);
514            if (mBlockLayout.Controls.IndexOf ( block ) == 1)
515                {
516                m_OffsetForFirstPhrase = node.Index;
517                //Console.WriteLine ( "Offset of strip is " + OffsetForFirstPhrase);
518               
519                }
520            if (mBlockLayout.Width > mContentView.Width - 50 )// to make more than 3 phrases visible in merge with empty section.
521                {
522                WrapContents = true;
523               
524                }
525            return block;
526            }
527
528        /// <summary>
529        /// Return the block after the selection. In the case of a strip it is the first block.
530        /// Return null if this goes past the last block, there are no blocks, or nothing was selected
531        /// in the first place.
532        /// </summary>
533        public Block BlockAfter(ISelectableInContentView item)
534        {
535            int count = mBlockLayout.Controls.Count;
536            int index = item is Strip ?
537                ((Strip)item).Selection is StripIndexSelection ? ((StripIndexSelection)((Strip)item).Selection).Index : 1 :
538                item is Block ? mBlockLayout.Controls.IndexOf((Control)item) + 2 :
539                item is StripCursor ? mBlockLayout.Controls.IndexOf((Control)item) + 1 : count;
540            return index < count ? (Block)mBlockLayout.Controls[index] : null;
541        }
542
543        /// <summary>
544        /// Return the block before the selection. In the case of a strip this is the last block.
545        /// Return null if this is before the first block, there are no blocks, or nothing was selected
546        /// in the first place.
547        /// </summary>
548        public Block BlockBefore(ISelectableInContentView item)
549        {
550            int index = item is Strip ?
551                ((Strip)item).Selection is StripIndexSelection ? ((StripIndexSelection)((Strip)item).Selection).Index - 1 :
552                    mBlockLayout.Controls.Count - 2 :
553                item is Block ? mBlockLayout.Controls.IndexOf((Control)item) - 2 :
554                item is StripCursor ? mBlockLayout.Controls.IndexOf((Control)item) - 1 : -1;
555            return index >= 0 ? (Block)mBlockLayout.Controls[index] : null;
556        }
557
558        /// <summary>
559        /// Find the block for the corresponding node inside the strip.
560        /// </summary>
561        public Block FindBlock(EmptyNode node)
562        {
563            // Note: we cannot rely on node.Index because we may want to find the block of a node that was deleted
564            // from the tree, and it does not have an index anymore. So let's just look for it.
565            foreach (Control c in mBlockLayout.Controls) if (c is Block && ((Block)c).Node == node) return (Block)c;
566            return null;
567        }
568
569        /// <summary>
570        /// Find the strip cursor at the given index.
571        /// </summary>
572        public StripCursor FindStripCursor(int index)
573        {
574            //@singleSection: replaced following three lines
575            //System.Diagnostics.Debug.Assert(index * 2 < mBlockLayout.Controls.Count, "No strip cursor at index");
576            //System.Diagnostics.Debug.Assert ( mBlockLayout.Controls.Count > index * 2    &&    mBlockLayout.Controls[index * 2] is StripCursor );
577            //return mBlockLayout.Controls.Count > index * 2? (StripCursor)mBlockLayout.Controls[index * 2] : null;
578
579        System.Diagnostics.Debug.Assert ( (index - OffsetForFirstPhrase) * 2 < mBlockLayout.Controls.Count, "No strip cursor at index" );
580        System.Diagnostics.Debug.Assert ( mBlockLayout.Controls.Count > (index - OffsetForFirstPhrase) * 2 && mBlockLayout.Controls[(index - OffsetForFirstPhrase) * 2] is StripCursor );
581        return mBlockLayout.Controls.Count > (index - OffsetForFirstPhrase) * 2 ? (StripCursor)mBlockLayout.Controls[(index - OffsetForFirstPhrase) * 2] : null;
582        }
583
584        //@singleSection
585        public Block FindBlockAtLocationInStrip ( int depth )
586            {
587            if ( depth < 0  || mBlockLayout.Controls.Count == 0) return null ;
588
589            for (int i = 0; i < mBlockLayout.Controls.Count;  i++)
590                {
591                if (mBlockLayout.Controls[i] is Block
592                    && mBlockLayout.Controls[i].Location.Y + mBlockLayout.Location.Y >= depth   )
593                    {
594                    return (Block)mBlockLayout.Controls[i];
595                    }
596                }
597            return null;
598            }
599
600        /// <summary>
601        /// Focus on the label.
602        /// </summary>
603        public void FocusStripLabel () { mLabel.Focus (); }
604
605        /// <summary>
606        /// Remove the block for the given node.
607        /// Remove the following strip cursor as well
608        /// (and the first one if it was the last block.)
609        /// </summary>
610        ///
611        public void RemoveBlock ( EmptyNode node )
612            {
613            RemoveBlock ( node, true );
614            }
615
616        private delegate void BlockRemoveInvokation ( EmptyNode node, bool updateSize ); // @phraseLimit
617
618        public void RemoveBlock(EmptyNode node, bool updateSize)
619        {
620            if (InvokeRequired)
621            {
622                Invoke ( new BlockRemoveInvokation ( RemoveBlock ), node, updateSize );
623            }
624        else
625            {
626            Block block = FindBlock ( node );
627            if (block != null)
628                {
629                int index = mBlockLayout.Controls.IndexOf ( block );
630                if (index < mBlockLayout.Controls.Count) mBlockLayout.Controls.RemoveAt ( index + 1 );
631                mBlockLayout.Controls.RemoveAt ( index );
632                if (mBlockLayout.Controls.Count == 1) mBlockLayout.Controls.RemoveAt ( 0 );
633                block.SizeChanged -= new EventHandler ( Block_SizeChanged );
634                if (updateSize) Resize_Blocks ();
635                //UpdateStripCursorsAccessibleName ( index - 1 );
636                UpdateStripCursorsAccessibleName (index> 3? index - 3 : 0 );
637
638                // dispose block for freeing window handle only if it is not held in clipboard @phraseLimit
639                if (mContentView.clipboard == null || (mContentView.clipboard != null && mContentView.clipboard.Node != block.Node))
640                    {
641                        if(mBlockLayout.Controls.Contains(block))  mBlockLayout.Controls.Remove(block);
642                    block.Dispose ();
643                    block = null;
644                    }
645
646                }
647            }
648        }
649
650
651        // @phraseLimit
652        /// <summary>
653        /// Remove and dispose all blocks in strip without removing phrases
654                /// </summary>
655        /// <param name="updateSize"></param>
656        /// <returns></returns>
657        public int RemoveAllBlocks ( bool updateSize )
658            {
659            int blocksRemovedCount = 0;
660            if (mBlockLayout.Controls.Count > 0)
661                {
662                    for (int i = mBlockLayout.Controls.Count - 1; i > 0; i--)
663                    {
664                    if (i >= mBlockLayout.Controls.Count) continue;
665
666                    if (mBlockLayout.Controls[i] is Block)
667                        {
668                        RemoveBlock ( (Block)mBlockLayout.Controls[i], updateSize );
669                        blocksRemovedCount++;
670                        }
671                    }
672                }
673                return blocksRemovedCount;
674            }
675
676        //@singleSection
677        public int RemoveAllFollowingBlocks ( bool removeHiddenBlocks, bool updateSize )
678            {
679            if ( FirstBlock == null ) return 0 ;
680
681            return RemoveAllFollowingBlocks ( FirstBlock.Node, removeHiddenBlocks, updateSize );
682            }
683
684//@singleSection
685        public int RemoveAllFollowingBlocks (EmptyNode node, bool removeTillHiddenBlocks ,bool updateSize )
686            {
687            int blocksRemovedCount = 0;
688            int limitIndex = node.Index - OffsetForFirstPhrase;//@singleSection
689            if (mBlockLayout.Controls.Count > 0)
690                {
691                for (int i = mBlockLayout.Controls.Count - 1; i > 0; i--)
692                    {
693                    if ( i >= mBlockLayout.Controls.Count) continue;
694
695                    if (mBlockLayout.Controls[i] is Block)
696                        {
697                        //if (((Block)mBlockLayout.Controls[i]).Node.Index <=  limitIndex
698                        if (((Block)mBlockLayout.Controls[i]).Node.Index <= node.Index
699                            ||    (removeTillHiddenBlocks && !IsContentViewFilledWithBlocks ) )
700                            {
701                            Console.WriteLine ("Removal of block till " + i.ToString ()) ;
702                            break;
703                            }
704
705                        RemoveBlock ( (Block)mBlockLayout.Controls[i], updateSize );
706                        blocksRemovedCount++;
707                        }
708                    }
709                }
710            return blocksRemovedCount;
711            }
712
713
714        // @phraseLimit
715        private delegate void QuickBlockRemoveInvokation ( Block block, bool updateSize ); // @phraseLimit
716
717        // @phraseLimit
718        /// <summary>
719        /// Remove and dispose a single block passed as parameter
720                /// </summary>
721        /// <param name="block"></param>
722        /// <param name="updateSize"></param>
723        private void RemoveBlock (Block block,  bool updateSize )
724            {
725            if (InvokeRequired)
726                {
727                Invoke ( new QuickBlockRemoveInvokation ( RemoveBlock ), block, updateSize );
728                }
729            else
730                {
731                        //Block block = (Block) mBlockLayout.Controls[i];
732                        if (block != null)
733                            {
734                            int index = mBlockLayout.Controls.IndexOf ( block );
735                            if (index < mBlockLayout.Controls.Count)
736                                {
737                                Control  stripCursorControl = mBlockLayout.Controls[index + 1];
738                                mBlockLayout.Controls.RemoveAt ( index + 1 );
739                                if (stripCursorControl != null && stripCursorControl is StripCursor)
740                                {
741                                    stripCursorControl.Dispose();
742                                }
743                                                                                                                                            }
744                            mBlockLayout.Controls.RemoveAt ( index );
745                            if (mBlockLayout.Controls.Count == 1) mBlockLayout.Controls.RemoveAt ( 0 );
746                            block.SizeChanged -= new EventHandler ( Block_SizeChanged );
747                            if (updateSize) Resize_Blocks ();
748                            //UpdateStripCursorsAccessibleName ( index - 1 );
749                            UpdateStripCursorsAccessibleName (index > 3? index-3: 0);
750
751                            // dispose block for freeing window handle only if it is not held in clipboard @phraseLimit
752                            if (mContentView.clipboard == null || (mContentView.clipboard != null && mContentView.clipboard.Node != block.Node))
753                                {
754                                block.Dispose ();
755                                block = null;
756                                }
757                            else // in case block is held in clipboard, just destroy handle
758                                block.DestroyBlockHandle ();
759                            }
760                        }
761            }
762
763
764
765        /// <summary>
766        /// Show the cursor at the current time in the waveform of the current playing block.
767        /// </summary>
768        public void SetSelectedAudioInBlockFromBlock(Block block, AudioRange audioRange)
769        {
770            mContentView.SelectionFromStrip = new AudioSelection((PhraseNode)block.Node, mContentView, audioRange);
771        }
772
773        /// <summary>
774        /// Set the current selected from the block itself. This gets passed to the content view.
775        /// </summary>
776        public void SetSelectedBlockFromBlock(Block block) { mContentView.SelectedNode = block.Node; }
777
778        /// <summary>
779        /// Set the selection from a strip cursor to its index. This gets passed to the content view.
780        /// </summary>
781        public void SetSelectedIndexFromStripCursor(StripCursor cursor)
782        {
783            int index = mBlockLayout.Controls.IndexOf(cursor) / 2;
784             m_TempCursor = cursor;
785            //mContentView.SelectionFromStrip = new StripIndexSelection(Node, mContentView, index);//@singleSection: original
786            mContentView.SelectionFromStrip = new StripIndexSelection ( Node, mContentView, index + OffsetForFirstPhrase);//@singleSection new
787        }
788
789        // @zoomwaveform
790        /// <summary>
791        /// Set the Animation Cursor
792        /// </summary>
793        public void SetAnimationCursor(int X, int Y, bool markOnPhrase,StripCursor cursor)
794        {
795            if (m_TempCursor == null)
796            {
797                SetSelectedIndexFromStripCursor(cursor);
798            }
799            if (m_TempCursor != null && mContentView.StripIsSelected)
800            {
801                if (cursor != m_TempCursor)
802                {
803                    m_TempCursor = cursor;
804                }
805                int index = mBlockLayout.Controls.IndexOf(m_TempCursor);
806                int tempTotalCount = mBlockLayout.Controls.Count;
807               
808                Control tempPreviousPhrase = null;
809                int tempWidthOfPreviousPhrase = 0;
810                Console.WriteLine("Index is {0}", index);
811                if (index > 0)
812                {
813                    tempPreviousPhrase = mBlockLayout.Controls[index - 1];
814                    tempWidthOfPreviousPhrase = tempPreviousPhrase.Width;
815                }
816                Control tempNextPhrase = null;
817                int tempWidthofNextPhrase = 0;
818                if (index < tempTotalCount - 1)
819                {
820                    tempNextPhrase = mBlockLayout.Controls[index + 1];
821                    tempWidthofNextPhrase = tempNextPhrase.Width;
822                }
823                //Point tempPreviousPos = mContentView.LocationOfBlockInStripPanel(tempPreviousPhrase);
824                //Point tempNextPos = mContentView.LocationOfBlockInStripPanel(tempNextPhrase);
825                Point cursorposition = mContentView.LocationOfBlockInStripPanel(m_TempCursor);
826                //  Console.WriteLine("Cursor Position is {0}", cursorposition);
827                Point LocationOfCursor = new Point(cursorposition.X + X, cursorposition.Y);
828                if (m_AnimationCursor == null)
829                {
830                    m_AnimationCursor = new StripCursor();
831                    this.Controls.Add(m_AnimationCursor);
832                }
833
834                if ((X < 0 && cursorposition.X - tempWidthOfPreviousPhrase - m_AnimationCursor.Width < LocationOfCursor.X) || (X > 0 && cursorposition.X + tempWidthofNextPhrase > LocationOfCursor.X))
835                {
836                    if ((tempPreviousPhrase == null && tempNextPhrase != null) ||
837                        (tempPreviousPhrase != null && tempNextPhrase == null) ||
838                        (tempNextPhrase != null && tempPreviousPhrase != null &&
839                         (tempPreviousPhrase.Top == tempNextPhrase.Top)))
840                    {
841                        m_AnimationCursor.Location = new Point(cursorposition.X + X, cursorposition.Y);
842                        m_AnimationCursor.SetHeight(mBlockHeight);
843                        m_AnimationCursor.BackColor = ColorSettings.StripSelectedBackColor;
844                        m_AnimationCursor.BringToFront();
845
846
847                        if (markOnPhrase)
848                        {
849
850                            if (tempNextPhrase != null && tempNextPhrase.Left < m_AnimationCursor.Right)
851                            {
852                                int relativeX = m_AnimationCursor.Left - tempNextPhrase.Left;
853                                if (relativeX > 0)
854                                {
855                                    if (tempNextPhrase is AudioBlock)
856                                        ((AudioBlock) tempNextPhrase).MarkSelection(relativeX);
857                                    mContentView.SplitAndMerge(false);
858                                }
859
860                            }
861                            else if (tempPreviousPhrase != null && m_AnimationCursor.Left < tempPreviousPhrase.Right)
862                            {
863                                int relativeX = m_AnimationCursor.Left - tempPreviousPhrase.Left;
864
865                                if ((relativeX - m_AnimationCursor.Width) > 0)
866                                {
867                                    if (tempPreviousPhrase is AudioBlock)
868                                        ((AudioBlock) tempPreviousPhrase).MarkSelection(relativeX -
869                                                                                        m_AnimationCursor.Width);
870                                    mContentView.SplitAndMerge(true);
871                                }
872
873                            }
874                        }
875                    }
876
877                }
878
879            }
880        }
881
882        // @zoomwaveform
883        /// <summary>
884        /// Set the Animation Cursor to null
885        /// </summary>
886        public void SetAnimationCursor()
887        {
888           if (this.Controls.Contains(m_AnimationCursor))
889                this.Controls.Remove(m_AnimationCursor);
890            m_AnimationCursor = null;
891            Console.WriteLine();
892        }
893
894        /// <summary>
895        /// Set the selection from the parent control view. (From ISelectableInContentView)
896        /// </summary>
897        public void SetSelectionFromContentView(NodeSelection selection)
898        {
899            SetAccessibleName();
900            Highlighted = !(selection is StripIndexSelection) && selection != null;
901        }
902
903        /// <summary>
904        /// Start renaming the strip.
905        /// </summary>
906        public void StartRenaming()
907        {
908            mContentView.ScrollStripsPanel_Top();
909            mLabel.Editable = true;
910            mContentView.SelectionFromStrip = new TextSelection(mNode, mContentView, Label);
911            SetAccessibleName();
912        }
913
914        /// <summary>
915        /// Get the strip index after the given (selected) item.
916        /// </summary>
917        public int StripIndexAfter(ISelectableInContentView item)
918        {
919            //int lastIndex = Node.PhraseChildCount;//@singleSection: original
920        int lastIndex = Node.PhraseChildCount - OffsetForFirstPhrase;//@singleSection: new
921            int index = item is Strip ?
922                ((Strip)item).Selection is StripIndexSelection ? ((StripIndexSelection)((Strip)item).Selection).Index + 1 : 0 :
923                item is Block ? (mBlockLayout.Controls.IndexOf((Control)item) + 1) / 2 :
924                item is StripCursor ? mBlockLayout.Controls.IndexOf((Control)item) / 2 + 1 : lastIndex + 1;
925            return index <= lastIndex ? index : lastIndex;
926        }
927
928        /// <summary>
929        /// Index in the strip before the selected item.
930        /// </summary>
931        public int StripIndexBefore(ISelectableInContentView item)
932        {
933            int index = item is Strip ?
934                ((Strip)item).Selection is StripIndexSelection ? ((StripIndexSelection)((Strip)item).Selection).Index - 1 :
935                    (mBlockLayout.Controls.Count - 1) / 2 :
936                item is Block ? mBlockLayout.Controls.IndexOf((Control)item) / 2 :
937                item is StripCursor ? mBlockLayout.Controls.IndexOf((Control)item) / 2 - 1 : -1;
938            return index >= 0 ? index : 0;
939        }
940
941        /// <summary>
942        /// Match the label (case independent) when searching.
943        /// </summary>
944        public string ToMatch() { return Label.ToLowerInvariant(); }
945
946        /// <summary>
947        ///  Updates labels of all blocks in a strip, to be used with   background worker
948        /// </summary>
949        private void UpdateBlockLabelsInStrip(object sender, DoWorkEventArgs e)
950            {
951            UpdateBlockLabelsInStrip () ;
952            }
953
954        /// <summary>
955        ///  Update labels of all blocks in a strip
956                /// </summary>
957            public void UpdateBlockLabelsInStrip () 
958        {
959            mLabelUpdateThread.WaitOne();
960            try
961            {
962                Control BlockControl = null;
963                for (int i = 0; i < mBlockLayout.Controls.Count; i++)
964                {
965                    BlockControl = mBlockLayout.Controls[i];
966                    if (BlockControl is Block)
967                    {
968                        ((Block)BlockControl).UpdateLabelsText();
969                    }
970                }
971            }
972            catch (System.Exception)
973            {
974            }
975            finally
976            {
977                mLabelUpdateThread.ReleaseMutex();
978            }
979        }
980
981        /// <summary>
982        /// Update the colors of the strip and its contents's.
983        /// </summary>
984        public void UpdateColors() { UpdateColors(ColorSettings); }
985
986        /// <summary>
987        /// Update the tab index for the strip and all of its blocks.
988        /// </summary>
989        public int UpdateTabIndex(int index)
990        {
991            TabIndex = index;
992            ++index;
993            foreach (Control c in mBlockLayout.Controls)
994            {
995                if (c is Block) index = ((Block)c).UpdateTabIndex(index);
996            }
997            return index;
998        }
999
1000        /// <summary>
1001        /// Update all waveforms in the strip with a given priority. (When rendering for the fist time, or selecting.)
1002        /// </summary>
1003        public void UpdateWaveforms(int priority)
1004        {
1005            foreach (Control c in mBlockLayout.Controls)
1006            {
1007                if (c is AudioBlock)
1008                {
1009                    mContentView.RenderWaveform(((AudioBlock)c).Waveform, priority);
1010                }
1011            }
1012        }
1013
1014
1015        // Add content view label to the accessible name of the strip when entering.
1016        private void AddContentsViewLabel()
1017        {
1018            SetAccessibleName();
1019            if (mContentView.IsEnteringView)
1020            {
1021                mLabel.AccessibleName = string.Format("{0} {1}", Localizer.Message("content_view"), mLabel.AccessibleName);
1022                Thread TrimAccessibleName = new Thread(new ThreadStart(TrimContentsViewAccessibleLabel));
1023                TrimAccessibleName.Start();
1024            }
1025        }
1026
1027        // Add a cursor at the given index (in the context of the block layout.)
1028        // Return the new cursor.
1029        private StripCursor AddCursorAtBlockLayoutIndex(int index)
1030        {
1031            StripCursor cursor = new StripCursor();
1032            cursor.SetHeight(mBlockHeight);
1033            cursor.ColorSettings = ColorSettings;
1034            cursor.TabStop = false;
1035            cursor.SetAccessibleNameForIndex(index / 2);
1036            mBlockLayout.Controls.Add(cursor);
1037            mBlockLayout.Controls.SetChildIndex(cursor, index);
1038            cursor.UpdateColors ();
1039            return cursor;
1040        }
1041
1042        // Compute the full width of the block layout that can accomodate all blocks.
1043        // This is exclusive of margins.
1044        private int BlockLayoutFullWidth
1045        {
1046            get
1047            {
1048                int w = 0;
1049                foreach (Control c in mBlockLayout.Controls) w += c.Width + c.Margin.Horizontal;
1050                return w;
1051            }
1052        }
1053
1054        // Get the minimum width necessary for the block layout to contain all blocks.
1055        private int BlockLayoutMinimumWidth
1056        {
1057            get
1058            {
1059                int w_min = 0;
1060                int count = mBlockLayout.Controls.Count;
1061                if (count > 2)
1062                {
1063                    // there is at least one block; the first block must fit the first two cursors
1064                    w_min = mBlockLayout.Controls[0].Width + mBlockLayout.Controls[0].Margin.Horizontal +
1065                        mBlockLayout.Controls[1].Width + mBlockLayout.Controls[1].Margin.Horizontal +
1066                        mBlockLayout.Controls[2].Width + mBlockLayout.Controls[2].Margin.Horizontal;
1067                    // following blocks are counted with the following cursor
1068                    for (int i = 3; i < mBlockLayout.Controls.Count - 1; i += 2)
1069                    {
1070                        int w = mBlockLayout.Controls[i].Width + mBlockLayout.Controls[i].Margin.Horizontal +
1071                            mBlockLayout.Controls[i + 1].Width + mBlockLayout.Controls[i + 1].Margin.Horizontal;
1072                        if (w > w_min) w_min = w;
1073                    }
1074                }
1075                return w_min;
1076            }
1077        }
1078
1079        // Size of the borders
1080        private int BorderHeight { get { return Bounds.Height - ClientSize.Height; } }
1081        private int BorderWidth { get { return Bounds.Width - ClientSize.Width; } }
1082
1083        // Get the height of the strip for the current block layout size/position.
1084        // Includes the border size.
1085        private int HeightForContents
1086        {
1087            get
1088            {
1089           
1090            return mBlockLayout.Location.Y + Math.Max ( mBlockHeight, mBlockLayout.Height ) +
1091                mBlockLayout.Margin.Bottom + BorderHeight;
1092            float sizeMultiplier = 1;//@singleSection
1093            //System.Media.SystemSounds.Asterisk.Play ();
1094                // determine how many blocks are visible w.r.t. total no. of phrases
1095            if (LastBlock != null ) //@singleSection
1096                {
1097                int lastBlockIndex = mBlockLayout.Controls.IndexOf ( LastBlock ) / 2;
1098                if (lastBlockIndex > 0  )
1099                    //&&                   (( mNode.PhraseChildCount - lastBlockIndex ) < 15
1100                    //||    lastBlockIndex <= 40    ||    lastBlockIndex %10 == 0))
1101                                    {
1102                                        sizeMultiplier = mNode.PhraseChildCount / lastBlockIndex;
1103                                        //Console.WriteLine ( "Phrase index : " + lastBlockIndex + " Strip height scale: " + sizeMultiplier );
1104                    }
1105                }
1106            //Console.WriteLine ( "block layout height " + this.Size.ToString());
1107                // If there are no contents, still show space for the block layout
1108                return mBlockLayout.Location.Y + Math.Max(mBlockHeight,mBlockLayout.Height*2  ) +
1109                    mBlockLayout.Margin.Bottom + BorderHeight;
1110            }
1111        }
1112
1113        //@singleSection
1114        public int PredictedStripHeight
1115            {
1116            get
1117                {
1118                float sizeMultiplier = 1;//@singleSection
1119                // determine how many blocks are visible w.r.t. total no. of phrases
1120                if (LastBlock != null) //@singleSection
1121                    {
1122                    int lastBlockIndex = mBlockLayout.Controls.IndexOf ( LastBlock ) / 2;
1123                    if (lastBlockIndex > 0)
1124                    //&&                   (( mNode.PhraseChildCount - lastBlockIndex ) < 15
1125                    //||    lastBlockIndex <= 40    ||    lastBlockIndex %10 == 0))
1126                        {
1127                        sizeMultiplier = mNode.PhraseChildCount / lastBlockIndex;
1128                        //Console.WriteLine ( "Phrase index : " + lastBlockIndex + " Strip height scale: " + sizeMultiplier );
1129                        }
1130                    }
1131                // If there are no contents, still show space for the block layout
1132                return mBlockLayout.Location.Y + Math.Max ( mBlockHeight, Convert.ToInt32 ( mBlockLayout.Height * sizeMultiplier ) ) +
1133                    mBlockLayout.Margin.Bottom + BorderHeight;
1134                }
1135            }
1136
1137        public void Resize_All() 
1138        {
1139            Resize_Label();
1140            Resize_Blocks(); 
1141        }
1142
1143        // Blocks are added, removed, or their width has changed after the audio scale changed.
1144        // Heights do not change, unless wrapping.
1145        private void Resize_Blocks()
1146        {
1147            if (mWrap)
1148            {
1149                Resize_Wrap();
1150               
1151            }
1152            else
1153            {
1154                // the block layout is resized to fit the blocks exactly; we use the last control to get the total width
1155                // Control k = mBlockLayout.Controls.Count > 0 ? mBlockLayout.Controls[mBlockLayout.Controls.Count - 1] : null;
1156                // int width_blocks = k == null ? mBlockLayout.Margin.Horizontal : k.Location.X + k.Width + k.Margin.Right;
1157                int width_blocks = BlockLayoutFullWidth;
1158                mBlockLayout.Width = width_blocks;
1159                Width = WidthForContents;
1160            }
1161        }
1162
1163        // Resize after the label has changed (edited or editable status changed)
1164        // This is not affected by the wrap contents setting.
1165        private void Resize_Label()
1166        {
1167            // move the block layout up or down if the label height has changed
1168            // and resize the strip accordingly
1169            mBlockLayout.Location = new Point(mBlockLayout.Location.X,
1170                mLabel.Location.Y + mLabel.Height + mLabel.Margin.Bottom + mBlockLayout.Margin.Top);
1171            Size = new Size(WidthForContents,
1172                mBlockLayout.Location.Y + mBlockLayout.Height + mBlockLayout.Margin.Bottom + BorderHeight);
1173        }
1174
1175        // Resize after the view has changed.
1176        // No effect when not wrapping.
1177        private void Resize_View()
1178        {
1179            if (mWrap)
1180            {
1181                //mContentView.PreStripResizeTasks();
1182                Resize_Wrap();
1183                mContentView.ResizeContentViewFromStripResize();
1184            }
1185        }
1186
1187        // Resize after wrapping has changed.
1188        private void Resize_Wrap()
1189        {
1190            if (mWrap)
1191            {
1192                mBlockLayout.AutoSize = true;
1193                mBlockLayout.AutoSizeMode = AutoSizeMode.GrowAndShrink;
1194                mBlockLayout.WrapContents = true;
1195                // The width of the block layout should fit the available space, unless it's narrower.
1196                // This may be overridden however by the minimum width to fit the widest waveform.
1197                int width_fit = mContentView.ClientRectangle.Width - Margin.Horizontal - BorderWidth -
1198                    mBlockLayout.Margin.Horizontal;
1199                mBlockLayout.MaximumSize =
1200                    new Size(Math.Max(BlockLayoutMinimumWidth, Math.Min(BlockLayoutFullWidth, width_fit)), 0);
1201                Size = new Size(WidthForContents, HeightForContents);
1202                ApplyFlowBreaks();
1203
1204            }
1205            else
1206            {
1207                mBlockLayout.AutoSize = false;
1208                mBlockLayout.WrapContents = false;
1209                mBlockLayout.MaximumSize = new Size(0, 0);
1210                mBlockLayout.Height = mBlockHeight;
1211                Height = HeightForContents;
1212                Resize_Blocks();
1213            }
1214        }
1215
1216        // Resize after the zoom factor has changed.
1217        private void Resize_Zoom()
1218        {
1219            if (mWrap)
1220            {
1221                Resize_Wrap();
1222            }
1223            else
1224            {
1225                mBlockLayout.Height = mBlockHeight;
1226                Height = mBlockLayout.Location.Y + mBlockLayout.Height + mBlockLayout.Margin.Bottom + BorderHeight;
1227                Resize_Blocks();
1228            }
1229        }
1230
1231        private void Resize_View(object sender, EventArgs e) { Resize_View(); }
1232
1233        // Set verbose accessible name for the strip
1234        public void SetAccessibleName()
1235        {
1236            if (Selection is StripIndexSelection)
1237            {
1238                mLabel.AccessibleName = Selection.ToString();
1239            }
1240            else
1241            {
1242                mLabel.AccessibleName = string.Concat(mNode.Used ? "" : Localizer.Message("unused"),
1243                    mNode.Label + " " ,
1244                    mNode.Duration == 0.0 ? Localizer.Message("empty") : string.Format(Localizer.Message("duration_s_ms"), mNode.Duration / 1000.0),
1245                    string.Format(Localizer.Message("section_level_to_string"), mNode.IsRooted ? mNode.Level : 0),
1246                    mNode.PhraseChildCount == 0 ? "" :
1247                        mNode.PhraseChildCount == 1 ? Localizer.Message("section_one_phrase_to_string") :
1248                            string.Format(Localizer.Message("section_phrases_to_string"), mNode.PhraseChildCount),
1249                ""); // @phraseLimit
1250            }
1251        }
1252
1253        // Reset the accessible name after a short while.
1254        private void TrimContentsViewAccessibleLabel()
1255        {
1256            Thread.Sleep(750);
1257            SetAccessibleName();
1258        }
1259
1260        // Udpate the color of the strip and its contents.
1261        private void UpdateColors(ColorSettings settings)
1262        {
1263            if (settings != null && mNode != null)
1264            {
1265                BackColor =
1266                mLabel.BackColor =
1267                    mBlockLayout.BackColor =
1268                    mHighlighted ? settings.StripSelectedBackColor :
1269                    mNode.Used ?( mNode.PhraseChildCount > 0 ? settings.StripBackColor : settings.StripWithoutPhrasesBackcolor ): settings.StripUnusedBackColor;
1270                                mLabel.ForeColor =
1271                    mHighlighted ? settings.StripSelectedForeColor :
1272                    mNode.Used ? settings.StripForeColor : settings.StripUnusedForeColor;
1273                mLabel.UpdateColors(settings);
1274                foreach (Control c in mBlockLayout.Controls)
1275                {
1276                    if (c is Block) ((Block)c).UpdateColors();
1277                    else if (c is StripCursor) ((StripCursor)c).UpdateColors();
1278                }
1279            }
1280        }
1281
1282        // Update the accessible label of the strip cursors after the given index.
1283        private void UpdateStripCursorsAccessibleName(int afterIndex)
1284        {
1285        //return;
1286            //for (int i = afterIndex + 2; i < mBlockLayout.Controls.Count; i += 2)
1287            for (int i = afterIndex ; i < mBlockLayout.Controls.Count; i += 2)
1288                {
1289                    int stripCursorIndex = i < mBlockLayout.Controls.Count - 1 && ((Block)mBlockLayout.Controls[i + 1]).Node.IsRooted ? ((Block)mBlockLayout.Controls[i + 1]).Node.Index :
1290        i > 1 && ((Block)mBlockLayout.Controls[i - 1]).Node.IsRooted? ((Block)mBlockLayout.Controls[i - 1]).Node.Index + 1 : 
1291        mBlockLayout.Controls.Count <=1?  OffsetForFirstPhrase : -1;
1292                    if (stripCursorIndex == -1) continue;
1293                //Console.WriteLine ( "strip cursor index " + stripCursorIndex + " " + i );
1294                System.Diagnostics.Debug.Assert ( mBlockLayout.Controls[i] is StripCursor );
1295                //((StripCursor)mBlockLayout.Controls[i]).SetAccessibleNameForIndex(i / 2);
1296                ((StripCursor)mBlockLayout.Controls[i]).SetAccessibleNameForIndex ( stripCursorIndex);
1297            }
1298        }
1299
1300        // Width of the strip to contain the label and the block layout, including borders.
1301        private int WidthForContents
1302        {
1303            get
1304            {
1305                int width_label = mLabel.Width + mLabel.Margin.Horizontal;
1306                int width_layout = mBlockLayout.Width + mBlockLayout.Margin.Horizontal;
1307                return Math.Max(width_label, width_layout) + BorderWidth;
1308            }
1309        }
1310
1311
1312        // Resize when a block size has changed.
1313        private void Block_SizeChanged(object sender, EventArgs e) { Resize_Blocks(); }
1314
1315        // Change the selection depending on the editable state of the label.
1316        private void Label_EditableChanged(object sender, EventArgs e)
1317        {
1318            if (mContentView != null)
1319            {
1320                mContentView.SelectionFromStrip = mLabel.Editable ?
1321                    new TextSelection(mNode, mContentView, mLabel.Label) :
1322                    new NodeSelection(mNode, mContentView);
1323            }
1324        }
1325
1326        // Update the label of the node after the user edited it.
1327        private void Label_LabelEditedByUser(object sender, EventArgs e)
1328        {
1329            if (mLabel.Label.Trim ()  != "")
1330            {
1331                DialogResult dialogResult = DialogResult.None;
1332                if (ContentView.Settings.Project_DisplayWarningsForEditOperations)
1333                {
1334                    dialogResult = MessageBox.Show(Localizer.Message("ConfirmSectionRename"), Localizer.Message("Caption_Warning"), MessageBoxButtons.OKCancel,MessageBoxIcon.Warning,MessageBoxDefaultButton.Button2);
1335                }
1336                if (dialogResult == DialogResult.Cancel)
1337                {
1338                    mLabel.Label = mNode.Label;
1339                    return;
1340                }
1341                if (dialogResult == DialogResult.None || dialogResult == DialogResult.OK)
1342                {
1343                    // update the label for the node
1344                    mContentView.RenameStrip(this);
1345                    mContentView.SelectionFromStrip = new NodeSelection(mNode, mContentView);
1346                }
1347                //else
1348                //{
1349                //    // restore the previous label from the node
1350                //    mLabel.Label = mNode.Label;
1351                //}
1352               
1353            }
1354            else
1355            {
1356                // restore the previous label from the node
1357                mLabel.Label = mNode.Label;
1358            }
1359        }
1360
1361        // Resize the strip according to the editable label, which size can change.
1362        private void Label_SizeChanged(object sender, EventArgs e)
1363        {
1364            int y = mBlockLayout.Location.Y;
1365            mBlockLayout.Location = new Point(mBlockLayout.Location.X,
1366                mLabel.Location.Y + mLabel.Height + mLabel.Margin.Bottom + mBlockLayout.Margin.Top);
1367            Size = new Size(Width, Height - y + mBlockLayout.Location.Y);
1368        }
1369
1370        // Select when tabbed into
1371        private void Strip_Enter(object sender, EventArgs e)
1372        {
1373            AddContentsViewLabel();
1374            mLabel.Focus();
1375            if ((mContentView.SelectedSection != mNode || mContentView.Selection is StripIndexSelection) &&
1376                !mContentView.Focusing && !this.IsCommentEditLabelActive)
1377            {
1378                mContentView.SelectedNode = mNode;
1379            }
1380        }
1381
1382        private void Strip_LocationChanged(object sender, EventArgs e)
1383        {
1384            Point offset = ((ScrollableControl)Parent).AutoScrollPosition;
1385            Point l = new Point(Location.X - offset.X, Location.Y - offset.Y);
1386            System.Diagnostics.Debug.Print("Location changed to {0}/{1}", Location, l);
1387        }
1388
1389        //@singleSection
1390        /// <summary>
1391        /// updates strip without updating its blocks
1392        /// </summary>
1393        public void RefreshStrip ()
1394            {
1395            Label = mNode.Label;
1396            //UpdateColors ();
1397            }
1398
1399
1400        //@singleSection
1401        private System.Windows.Forms.FlowLayoutPanel m_BackgroundBlockLayout;
1402        private FlowLayoutPanel CreateBackUpLayout ()
1403            {
1404            FlowLayoutPanel backupBlockLayout = new FlowLayoutPanel ();
1405            backupBlockLayout.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
1406            backupBlockLayout.BackColor = System.Drawing.Color.GreenYellow;
1407            backupBlockLayout.Location = new System.Drawing.Point ( this.Width, 78 );
1408            backupBlockLayout.Margin = new System.Windows.Forms.Padding ( 3, 0, 3, 0 );
1409            backupBlockLayout.Name = "m_BackgroundBlockLayout";
1410            backupBlockLayout.Size = new System.Drawing.Size ( 303, 109 );
1411            backupBlockLayout.TabIndex = 1;
1412            backupBlockLayout.WrapContents = true;
1413            backupBlockLayout.Click += new System.EventHandler ( this.Strip_Enter );
1414            backupBlockLayout.BackColor = mHighlighted ? ColorSettings.StripSelectedBackColor :
1415                    mNode.Used ? (mNode.PhraseChildCount > 0 ? ColorSettings.StripBackColor : ColorSettings.StripWithoutPhrasesBackcolor) : ColorSettings.StripUnusedBackColor;
1416
1417            this.Controls.Add ( backupBlockLayout );
1418            return backupBlockLayout;
1419            }
1420
1421
1422        EmptyNode m_BackgroundPhrasesLoadStartNode;
1423        EmptyNode m_BackgroundPhrasesLoadEndNode;
1424        public void LoadBackUpLayout ( EmptyNode startNode, EmptyNode endNode )
1425            {
1426            m_BackgroundBlockLayout = CreateBackUpLayout ();
1427            m_BackgroundPhrasesLoadStartNode = startNode;
1428            m_BackgroundPhrasesLoadEndNode = endNode;
1429            m_BackgroundPhrasesLoadStartIndex = -1;
1430            m_BackgroundPhrasesloadTimer.Interval = 600;
1431            m_BackgroundPhrasesloadTimer.Tick += new EventHandler ( BackgroundPhrasesloadTimer_tick );
1432            m_BackgroundPhrasesloadTimer.Start ();
1433
1434            }
1435
1436        System.Windows.Forms.Timer m_BackgroundPhrasesloadTimer = new System.Windows.Forms.Timer ();
1437
1438        int m_BackgroundPhrasesLoadStartIndex = -1;
1439        int m_BackgroundPhrasesLoadEndIndex = -1;
1440        private void BackgroundPhrasesloadTimer_tick ( object sender, EventArgs e )
1441            {
1442            m_BackgroundPhrasesloadTimer.Stop ();
1443
1444            if (m_BackgroundPhrasesLoadStartIndex == -1)
1445                m_BackgroundPhrasesLoadStartIndex = m_BackgroundPhrasesLoadStartNode.Index;
1446            else
1447                m_BackgroundPhrasesLoadStartIndex = m_BackgroundPhrasesLoadEndIndex + 1;
1448
1449            m_BackgroundPhrasesLoadEndIndex = m_BackgroundPhrasesLoadStartIndex + 10;
1450            if (m_BackgroundPhrasesLoadEndIndex > m_BackgroundPhrasesLoadEndNode.Index) m_BackgroundPhrasesLoadEndIndex = m_BackgroundPhrasesLoadEndNode.Index;
1451
1452            BackUpLayoutBlockAddsRangeOfBlocks ( mNode.PhraseChild ( m_BackgroundPhrasesLoadStartIndex ), mNode.PhraseChild ( m_BackgroundPhrasesLoadEndIndex ) );
1453
1454            if (m_BackgroundPhrasesLoadEndIndex == m_BackgroundPhrasesLoadEndNode.Index)
1455                {
1456                m_BackgroundPhrasesLoadStartIndex = -1;
1457                m_BackgroundPhrasesloadTimer.Stop ();
1458                UpdateColors ();
1459                m_BackgroundBlockLayout.Location =new Point ( mBlockLayout.Location.X, m_BackgroundBlockLayout.Height * -1 ) ;
1460                //Console.WriteLine ( "background layout created " + m_BackgroundPhrasesLoadStartIndex + " - " + m_BackgroundPhrasesLoadEndIndex );
1461                }
1462            else
1463                {
1464                m_BackgroundPhrasesloadTimer.Start ();
1465                //Console.WriteLine ( "console timer starting  " + m_BackgroundPhrasesLoadStartIndex + " - " + m_BackgroundPhrasesLoadEndIndex );
1466                }
1467            }
1468
1469        //@singleSection
1470        public Block BackUpLayoutBlockAddsRangeOfBlocks ( EmptyNode startNode, EmptyNode endNode )
1471            {
1472            if (InvokeRequired)
1473                {
1474                return (Block)Invoke ( new BlockRangeCreationInvokation ( BackUpLayoutBlockAddsRangeOfBlocks ), startNode, endNode );
1475                }
1476            else
1477                {
1478                for (int i = startNode.Index; i <= endNode.Index; ++i)
1479                    {
1480                    BackupLayout_CreateBlockForNode ( mNode.PhraseChild ( i ), endNode.Index == i ? true : false );
1481
1482                    }
1483
1484                return null;
1485                }
1486            }
1487
1488
1489        //@singleSection
1490        private Block BackupLayout_CreateBlockForNode ( EmptyNode node, bool updateSize )
1491            {
1492            //MessageBox.Show ( node.Index.ToString () );
1493            if (m_BackgroundBlockLayout.Controls.Count == 0)
1494                {
1495                //@ StripCursor cursor = AddCursorAtBlockLayoutIndex ( 0 );
1496                int index = 0;
1497                StripCursor cursor = new StripCursor ();
1498                cursor.SetHeight ( mBlockHeight );
1499                cursor.ColorSettings = ColorSettings;
1500                cursor.TabStop = false;
1501                cursor.SetAccessibleNameForIndex ( index / 2 );
1502                m_BackgroundBlockLayout.Controls.Add ( cursor );
1503                m_BackgroundBlockLayout.Controls.SetChildIndex ( cursor, index );
1504                }
1505            Block block = node is PhraseNode ? new AudioBlock ( (PhraseNode)node, this, mContentView.Settings.Project_ShowWaveformInContentView ) : new Block ( node, this );
1506            m_BackgroundBlockLayout.Controls.Add ( block );
1507            //@singleSection: following 2 lines replaced
1508            //mBlockLayout.Controls.SetChildIndex(block, 1 + 2 * node.Index);
1509            //AddCursorAtBlockLayoutIndex(2 + 2 * node.Index);
1510
1511            m_BackgroundBlockLayout.Controls.SetChildIndex ( block, 1 + 2 * (node.Index) );
1512            //@ AddCursorAtBlockLayoutIndex ( 2 + 2 * (node.Index - OffsetForFirstPhrase) );
1513            //--
1514            StripCursor cursor1 = new StripCursor ();
1515            int index1 = 2 + 2 * node.Index;
1516            cursor1.SetHeight ( mBlockHeight );
1517            cursor1.ColorSettings = ColorSettings;
1518            cursor1.TabStop = false;
1519            cursor1.SetAccessibleNameForIndex ( index1 / 2 );
1520            m_BackgroundBlockLayout.Controls.Add ( cursor1 );
1521            m_BackgroundBlockLayout.Controls.SetChildIndex ( cursor1, index1 );
1522            //---
1523
1524            block.SetZoomFactorAndHeight ( mContentView.ZoomFactor, mBlockHeight );
1525            block.Cursor = Cursor;
1526            block.SizeChanged += new EventHandler ( Block_SizeChanged );
1527
1528            //@ if (updateSize) Resize_Blocks ();
1529
1530            //@ UpdateStripCursorsAccessibleName ( 2 + 2 * node.Index );
1531            //---
1532            m_BackgroundBlockLayout.AutoSize = true;
1533            m_BackgroundBlockLayout.AutoSizeMode = AutoSizeMode.GrowAndShrink;
1534            m_BackgroundBlockLayout.WrapContents = true;
1535            // The width of the block layout should fit the available space, unless it's narrower.
1536            // This may be overridden however by the minimum width to fit the widest waveform.
1537            int width_fit = mContentView.ClientRectangle.Width - Margin.Horizontal - BorderWidth -
1538                m_BackgroundBlockLayout.Margin.Horizontal;
1539            m_BackgroundBlockLayout.MaximumSize =
1540                new Size ( Math.Max ( BlockLayoutMinimumWidth, Math.Min ( BlockLayoutFullWidth, width_fit ) ), 0 );
1541            Size = new Size ( WidthForContents, HeightForContents );
1542            //---
1543            //System.Media.SystemSounds.Asterisk.Play ();
1544            return block;
1545            }
1546
1547        public void ReplaceBlockLayout ()
1548            {
1549            if (m_BackgroundBlockLayout.Controls.Count == 0) return;
1550            Point layoutPoint = mBlockLayout.Location;
1551            if (this.Controls.Contains (mBlockLayout )) this.Controls.Remove (mBlockLayout) ;
1552            mBlockLayout.Dispose ();
1553            m_BackgroundBlockLayout.Location = layoutPoint;
1554            mBlockLayout = m_BackgroundBlockLayout;
1555            }
1556
1557        //@singleSection
1558        public void MoveCurrentBlocklayoutToBackground ()
1559            {
1560            if (m_BackgroundBlockLayout != null)
1561                {
1562                this.Controls.Remove ( m_BackgroundBlockLayout );
1563                m_BackgroundBlockLayout.Dispose ();
1564                if (ContentView.Settings != null &&  ContentView.Settings.Project_OptimizeMemory)
1565                {
1566                    Console.WriteLine("Background layout memory before collection :" + (System.GC.GetTotalMemory(false) / (1024 * 1024)).ToString());
1567                    //System.GC.Collect();
1568                    Console.WriteLine("Background layout memory after collection :" + (System.GC.GetTotalMemory(false) / (1024 * 1024)).ToString());
1569                }
1570                }
1571            m_BackgroundBlockLayout = mBlockLayout;
1572            m_BackgroundBlockLayout.Location = new Point ( this.Location.X, Convert.ToInt32( m_BackgroundBlockLayout.Height * -1.2 ));
1573            mBlockLayout = CreateBackUpLayout ();
1574            mBlockLayout.Location = new System.Drawing.Point ( 3, 78 );
1575            Resize_All ();
1576            //Console.WriteLine ( "move to background  " + "size : " + m_BackgroundBlockLayout.Size + " location : " + m_BackgroundBlockLayout.Location);
1577            // if previous block layout is not completely created, remove it
1578            // this will avoid of overlapping phrases
1579            if (m_BackgroundBlockLayout.Height == 0)
1580            {
1581                this.Controls.Remove(m_BackgroundBlockLayout);
1582                m_BackgroundBlockLayout.Dispose ();
1583                m_BackgroundBlockLayout = null;
1584                Console.WriteLine("in complete background layout removed");
1585            }
1586            }
1587
1588
1589        //@singleSection
1590        public bool DisplayPreviousLayout ( EmptyNode expectedLastPhrase)
1591            {
1592            if (m_BackgroundBlockLayout == null || m_BackgroundBlockLayout.Controls.Count < 2) return false;
1593
1594            bool isExpectedPhraseExists = false;
1595            bool isBlocksContineus = true;
1596            int previousNodeIndex = -1;
1597            for (int i = m_BackgroundBlockLayout.Controls.Count - 1; i >= 0; --i)
1598                {
1599                if (m_BackgroundBlockLayout.Controls[i] is Block )
1600                    {
1601                        EmptyNode iterationNode = ((Block)m_BackgroundBlockLayout.Controls[i]).Node;
1602                        if (iterationNode == expectedLastPhrase)
1603                        {
1604                            isExpectedPhraseExists = true;
1605                            //break;
1606                        }
1607                        if (previousNodeIndex != -1 &&  iterationNode.IsRooted && iterationNode.Index != previousNodeIndex - 1)
1608                        {
1609                            isBlocksContineus = false;
1610                        }
1611                        if (iterationNode.IsRooted) previousNodeIndex = iterationNode.Index;
1612                    }
1613                }
1614            if (!isExpectedPhraseExists || !isBlocksContineus) return false;
1615            // determine the first phrase, and return if no suitable phrase found
1616            int newOffset = -1;
1617            for (int i = 0; i < m_BackgroundBlockLayout.Controls.Count; i++)
1618            {
1619                if (m_BackgroundBlockLayout.Controls[i] is Block && ((Block)m_BackgroundBlockLayout.Controls[i]).Node.IsRooted)
1620                {
1621                    newOffset = ((Block)m_BackgroundBlockLayout.Controls[i]).Node.Index;
1622                }
1623            }
1624            if (newOffset == -1) return false;
1625
1626            Point layoutLocation = new Point ( mBlockLayout.Location.X , mBlockLayout.Location.Y ) ;
1627            FlowLayoutPanel removePanel = mBlockLayout;
1628            removePanel.SendToBack ();
1629            this.Controls.Remove ( removePanel );
1630
1631            mBlockLayout = m_BackgroundBlockLayout;
1632            m_OffsetForFirstPhrase = newOffset;
1633            mBlockLayout.Location = layoutLocation;
1634            mBlockLayout.BringToFront ();
1635            // scan all blocks in cashed layout and remove blocks that are detached
1636            for (int i = mBlockLayout.Controls.Count - 1; i > 0; i--)
1637            {
1638                if (i > mBlockLayout.Controls.Count - 1) i = mBlockLayout.Controls.Count - 1;
1639                if (mBlockLayout.Controls[i] is Block && !((Block)mBlockLayout.Controls[i]).Node.IsRooted)
1640                {
1641                    RemoveBlock((Block)mBlockLayout.Controls[i], true);
1642                }
1643            }
1644
1645            Resize_All ();
1646            if (removePanel != null )   removePanel.Dispose ();
1647            //Console.WriteLine ( "Displaying previous layout  : size : location " + mBlockLayout.Size + " : " + mBlockLayout.Location);
1648            return true;
1649            }
1650
1651        //@singleSection
1652        public void CreateNewLayout ( bool preserveExistingLayout )
1653            {
1654            FlowLayoutPanel oldBlocklayout = mBlockLayout;
1655            oldBlocklayout.SendToBack ();
1656            mBlockLayout = CreateBackUpLayout ();
1657            mBlockLayout.Location = new System.Drawing.Point ( 3, 78 );
1658            mBlockLayout.BringToFront ();
1659           
1660            if (!preserveExistingLayout)
1661                {
1662                this.Controls.Remove ( oldBlocklayout );
1663                oldBlocklayout.Dispose ();
1664                }
1665            Resize_All ();
1666            }
1667
1668        //@singleSection
1669        public Block FirstBlockInNextLineOrPrevious ( EmptyNode node , bool nextLine)
1670            {
1671            if ( node == null ) return null ;
1672            Block currentBlock = FindBlock ( node );
1673            if (currentBlock != null)
1674                {
1675                int blockHeight = nextLine ? currentBlock.Height : Convert.ToInt32 (currentBlock.Height * 1.2) * -1 ;
1676                return FindBlockAtLocationInStrip ( currentBlock.Location.Y + mBlockLayout.Location.Y + blockHeight);
1677                }
1678            //Console.WriteLine ( " returning null " );
1679            return null;
1680
1681            }
1682
1683
1684            private bool m_IsFlowBreakMarked = false;
1685            private void ApplyFlowBreaks()
1686            {
1687                //Console.WriteLine("width of strip " + Width);
1688               
1689                if (mBlockLayout != null && mBlockLayout.WrapContents && mBlockLayout.Controls.Count > 1)
1690                {
1691                    if (!mContentView.Settings.Project_LeftAlignPhrasesInContentView)
1692                    {
1693                        if (m_IsFlowBreakMarked)
1694                        {
1695                            foreach (Control c in mBlockLayout.Controls)
1696                            {
1697                                if (mBlockLayout.GetFlowBreak(c)) mBlockLayout.SetFlowBreak(c, false);
1698                               
1699                            }
1700                            m_IsFlowBreakMarked = false;
1701                        }
1702                        return;
1703                    }
1704
1705int boundaryWidth = mContentView.ClientRectangle.Width - Margin.Horizontal;
1706                    //Console.WriteLine("boundary width " + boundaryWidth);
1707                    if (!m_IsFlowBreakMarked && Width <= boundaryWidth) return;
1708
1709                    int firstBlockX = -1;
1710                    Point previousMarkedBlockLocation =  new Point (0,0);
1711                    foreach (Control c in mBlockLayout.Controls)
1712                    {
1713                        if (c is Block)
1714                        {//2
1715                            //Console.WriteLine("block " + mBlockLayout.Controls.IndexOf(c));
1716                            if (firstBlockX < 0) firstBlockX = c.Location.X;
1717
1718                            bool isMarkedOnCurrentControl = false;
1719                            if (m_IsFlowBreakMarked)
1720                            {//3
1721                                isMarkedOnCurrentControl = mBlockLayout.GetFlowBreak(c);
1722
1723                                if (isMarkedOnCurrentControl)
1724                                {//4
1725                                    //Console.WriteLine("marked on " + c.Location);
1726                                    if (c.Location.X <= boundaryWidth || Width <= boundaryWidth)
1727                                    {//5
1728                                        mBlockLayout.SetFlowBreak(c, false);
1729                                        isMarkedOnCurrentControl = false;
1730                                        m_IsFlowBreakMarked = false;
1731                                        //Console.WriteLine("removing flow break mark in " + c.Location);
1732                                    }//-5
1733                                    else
1734                                    {//5
1735                                        m_IsFlowBreakMarked = true;
1736                                        isMarkedOnCurrentControl = true;
1737                                        //Console.WriteLine("leaving flow break for " + c.Location);
1738                                    }//-5
1739                                }//-4
1740                            }//--3
1741                            //Console.WriteLine(Width + " : " + boundaryWidth);
1742                            if (Width > boundaryWidth
1743                                && !isMarkedOnCurrentControl
1744                                && ((c.Location.X > boundaryWidth || (c.Width > boundaryWidth && c.Location.X > firstBlockX))
1745                                                                || (previousMarkedBlockLocation.Y == c.Location.Y && previousMarkedBlockLocation.X - c.Location.X > boundaryWidth)))
1746                            {//3
1747                                mBlockLayout.SetFlowBreak(c, true);
1748                                m_IsFlowBreakMarked = true;
1749                                isMarkedOnCurrentControl = true;
1750                                //Console.WriteLine("position of block " + c.Location.X);
1751                            }//-3
1752                            else if (isMarkedOnCurrentControl)
1753                            {//3
1754                                //Console.WriteLine("position of block - existing mark " + c.Location.X);
1755                                m_IsFlowBreakMarked = true;
1756                            }//-3
1757                            if (isMarkedOnCurrentControl) previousMarkedBlockLocation = new Point(c.Location.X, c.Location.Y);
1758
1759                            if (!m_IsFlowBreakMarked
1760                                && (isMarkedOnCurrentControl || mBlockLayout.GetFlowBreak(c)))
1761                            {//3
1762                                if (Width <= boundaryWidth)
1763                                {//4
1764                                    mBlockLayout.SetFlowBreak(c, false);
1765                                    //Console.WriteLine("removing mark on left over " + c.Location);
1766                                }//-4
1767                                else
1768                                {//4
1769                                    m_IsFlowBreakMarked = true;
1770                                }//-4
1771                            }    //-3
1772                        }//-2
1773                       
1774                    }// end foreach
1775                    if (this.Width < mBlockLayout.Width || this.Height < mBlockLayout.Height) Size = new Size(WidthForContents, HeightForContents);
1776                }
1777            }
1778
1779        public void VerifyFlowBreak()
1780        {
1781            bool isMarked = false;
1782            foreach (Control c in mBlockLayout.Controls)
1783            {
1784                if (c is Block &&  mBlockLayout.GetFlowBreak(c))
1785                {
1786                    Console.WriteLine("verification : is marked on " + c.Location);
1787                    isMarked = true;
1788                }
1789            }
1790           
1791            MessageBox.Show ("New line mark on blocks = " + isMarked.ToString ()) ; 
1792        }
1793
1794        public void DestroyStripHandle ()
1795            {
1796            this.DestroyHandle ();
1797            }
1798
1799        private void Strip_Disposed(object sender, EventArgs e)
1800        {
1801            if (mContentView != null )  mContentView.SizeChanged -= new EventHandler(Resize_View);
1802        }
1803        public bool IsCommentEditLabelActive
1804        {
1805            get
1806            {
1807                return this.Controls.Contains(m_EditableLabel);
1808            }
1809        }
1810        public void ShowEditLabelToAddComment()
1811        {
1812            if (mContentView.Selection is AudioSelection)
1813            {
1814                m_TimeOfCursor = ((AudioSelection)mContentView.Selection).AudioRange.CursorTime;               
1815            }
1816            EditableLabel editLabel = new EditableLabel(mContentView.Selection.Node as EmptyNode);
1817            this.Controls.Add(editLabel);
1818            m_EditableLabel = editLabel;
1819            m_SelectedNodeToAddComment = mContentView.Selection.Node as EmptyNode;
1820            editLabel.Show();
1821            editLabel.Editable = true;
1822            AlignCommentEditLabel();
1823            editLabel.BringToFront();
1824            editLabel.AddComment += new EventHandler(EditableLabel_AddComment);
1825            editLabel.CloseComment += new EventHandler(EditLabel_CloseAddComment);
1826        }
1827
1828        private void EditableLabel_AddComment(object sender, EventArgs e)
1829        {
1830            Block tempBlock = FindBlock(m_SelectedNodeToAddComment);
1831            if (tempBlock != null)
1832            {
1833
1834                mContentView.ToggleTODOForPhrase(m_EditableLabel.CommentText);
1835                mContentView.AddCommentOnTodoPhrase(m_EditableLabel.CommentText);
1836                tempBlock.UpdateLabelsText();
1837                //tempBlock.SetZoomFactorAndHeight(mContentView.ZoomFactor, mBlockHeight);
1838                tempBlock.AlignLabelToShowCommentIcon();
1839                RemoveEditLabelControlForAddingComment();
1840
1841            }
1842        }
1843
1844        private void EditLabel_CloseAddComment(object sender, EventArgs e)
1845        {
1846            RemoveEditLabelControlForAddingComment();
1847        }
1848
1849        public void RemoveEditLabelControlForAddingComment()
1850        {
1851            m_EditableLabel.AddComment -= new EventHandler(EditableLabel_AddComment);
1852            m_EditableLabel.CloseComment -= new EventHandler(EditLabel_CloseAddComment);
1853
1854            if (m_TimeOfCursor != 0 && m_SelectedNodeToAddComment is PhraseNode)
1855            {
1856                mContentView.Selection = new AudioSelection((PhraseNode)m_SelectedNodeToAddComment, mContentView,
1857                    new AudioRange(m_TimeOfCursor));
1858            }
1859            else
1860            {
1861                mContentView.Selection = new NodeSelection(m_SelectedNodeToAddComment, mContentView);
1862            }
1863            m_TimeOfCursor = 0;
1864
1865            this.Controls.Remove(m_EditableLabel);
1866        }
1867        public void AlignCommentEditLabel()
1868        {
1869
1870            Block tempBlock = FindBlock(m_SelectedNodeToAddComment);
1871            if ((this.Size.Width - tempBlock.Location.X) >= m_EditableLabel.Size.Width)
1872            {
1873                m_EditableLabel.Location = new Point(tempBlock.Location.X, tempBlock.Location.Y);
1874            }
1875            else
1876            {
1877                int tempVal = (this.Size.Width - m_EditableLabel.Size.Width);
1878                m_EditableLabel.Location = new Point(tempVal, tempBlock.Location.Y);
1879            }
1880        }
1881        public void AlignLabelToShowCommentIcon()
1882        {
1883            if (mContentView.Selection.Node is EmptyNode)
1884            {
1885                Block tempBlock = FindBlock(mContentView.Selection.Node as EmptyNode);
1886                tempBlock.UpdateLabelsText();
1887                tempBlock.AlignLabelToShowCommentIcon();
1888            }
1889        }
1890    }
1891}
Note: See TracBrowser for help on using the repository browser.