/* a SortedCollection of TRviewInfo (for TraceBrowser) */!!

inherit(SortedCollection, #TRviewCollection, nil, 2, 0)!!

now(class(TRviewCollection))!!

/* PUBLIC */
Def new(self | instance)
{
   instance := newWithCompareBlock(self:ancestor, 
                                   1, 
                                   {using(a, b)
                                     viewStartLine(a) < viewStartLine(b)}
                                  ) ;
   ^instance
}
!!

now(TRviewCollection)!!

/* PRIVATE -- add offset to all elements of viewColl */
Def adjustViewCollOffset(self, offset)
{
  do(self,
  {using(viewInfo)
     offsetViewStartLine( viewInfo, offset )
  });
}
!!

/* PUBLIC -- return the view which contains viewStartLine 0. */
Def focusView(self)
{
  if (size(self) = 0) then ^nil endif ;

  do(self,
  {using(viewInfo)
      if ((viewStartLine(viewInfo) <= 0) cand (0 <= viewEndLine(viewInfo)))
      then
        ^viewInfo
      endif ;
  });
  displayFormattedError(ErrorTextLibClass$Inst, 
     ER_INTERNAL, FORCE_POPUP, "trviewco", "No viewStartLine = 0", nil);
  ^nil /* internal error */
}
!!

/* PUBLIC 
  visLines are 0..lastLineNum; execute aBlock for each text line visible.
  aBlock takes 2 args: [1] textString, [2] display line # (from 0)
  Ex: foreachVisibleLine( aTRviewColl, 
                          visLines(self),
                          {using(textStr, lineNum)
                           Call TextOut(hDC, 
                                        0, /* xPixelPos *\
                                        (lineNum * tmHeight), /* yPixelPos *\
                                        textStr,
                                        size(textStr)
                          }
                        ) ; 
*/
Def foreachVisibleLine(self, lastLineNum, aBlock)
{
  do(self,
  {using(view | textColl, bufIndex, indexLimit, displayLineNumber)
    if view cand (textColl := bufText(view))
    then
      displayLineNumber := viewStartLine( view ) ;
      bufIndex := 0 ;
      indexLimit := size( textColl ) ;
      loop while (bufIndex < indexLimit)
      begin 
        if (displayLineNumber >= 0) cand (displayLineNumber <= lastLineNum)
        then
          eval( aBlock, textColl[bufIndex], displayLineNumber ) ;
        endif ;
        displayLineNumber := ( displayLineNumber + 1 ) ;
        bufIndex := ( bufIndex + 1 ) ;
      endLoop;
    endif ;
  });
  
}
!!

/* PRIVATE
   Return the number of lines of text in the cache.
*/
Def numLinesIn(self)
{
  ^size( self )    /* synonym */
}
!!
/* PRIVATE
   Return the number of lines of text in the cache which are numbered
   less than zero (based on viewStartLine).
*/
Def prefixLinesHiddenIn(self | num)
{
  if (size(self) = 0)
  then
    ^0
  else
    num := viewStartLine( first(self) ) ;
    if (num < 0)
    then
      ^num
    else
      ^0
    endif ;
  endif ;
}
!!

/* PRIVATE
   Return the number of lines of text in the cache.
*/
Def size(self | numLines)
{
  numLines := 0 ;
  do(self,
  {using(view)
    numLines := (numLines + size(view));
  });

  ^numLines
}
!!

/* PRIVATE 
  ViewPort has been resized.  ViewStartLine numbering is correct.
  Trim unneeded viewInfo's from self.
*/
Def trimDisplayViews(self, numLinesInDisplay | displayMargin aView)
{
/* displayMargin is the number of lines to keep outside of the
   display range. {@@tuning parameter@@}
*/
  displayMargin := -15 ; /* N.B. must be negative! See usage, below */

  /* trim from top */
  loop while (size(self) > 0)
        cand (aView := first(self))
        cand (viewEndLine(aView) < displayMargin) /* margin is negative */
  begin 
    removeFirst(self);
  endLoop;
  
  /* trim from bottom */
  displayMargin := ( numLinesInDisplay - displayMargin ) ;
  /* (i.e. the above adds displayMargin) */
  loop while (size(self) > 0) 
        cand (aView := last(self))
        cand (viewStartLine(aView) > displayMargin)
  begin 
    removeLast(self)
  endLoop;
}
!!


/* PRIVATE
   Given display lineNum, return #(viewInfo, lineTextStr) or nil.
*/
Def viewFromLine(self, lineNum | viewInfo)
{
  do(self,
  {using(view)
    if (lineNum >= viewStartLine(view)) cand (lineNum <= viewEndLine(view))
    then viewInfo := view ;
    endif ;
  });
  if not(viewInfo)
  then
    ^nil
  else
    ^tuple( viewInfo, viewLineStr(viewInfo, lineNum) )
  endif ;
}

!!
