dps/src/SimpleTextDLE.m3


Copyright (C) 1994, Digital Equipment Corp.

MODULE SimpleTextDLE;

IMPORT DisplayList, DPS, DPSWindow, Text, Fmt;

CONST xMargin = 5.0;
CONST yMargin = 3.0;
CONST fontHeight = DPS.StandardFontPoints;
CONST fontDescender = 2.0;
CONST lineEscapement = 20.0;

PROCEDURE Repaint (e: E; box: DPS.Box; <*UNUSED*> only: REFANY): TEXT =
 VAR lineCount: INTEGER;
 VAR data: TEXT := "";
  BEGIN
  IF NOT DPS.BoxesIntersect (e.box, box) THEN RETURN NIL; END;
  data := DPS.EdgedBoxClipAndPaint (e.box);
  lineCount := NUMBER (e.lines^);
  FOR line := 0 TO lineCount-1 DO
    data := data & " "
      & Fmt.Real(e.box.low.x + xMargin) & " "
      & Fmt.Real (e.box.low.y + yMargin + fontDescender
         + FLOAT(lineCount-line-1) * lineEscapement )
      & " moveto "
      & " (" & e.lines[line] & ") " (* EscapeText called at Init time. *)
      & " ButtonDLEFont setfont 0.0 setgray show ";
    END;
  RETURN " gsave " & data & " grestore ";
  END Repaint;

PROCEDURE Init (e: E; window: DPSWindow.T) =
  BEGIN
  IF e.initialized THEN RETURN; END;
  window.SendFoundation ( " /ButtonDLEFont /Times-Roman findfont "
    & Fmt.Real(fontHeight) & " scalefont def " ); (* Many times alas. *)
  Recalculate (e, window);
  e.initialized := TRUE;
  END Init;

PROCEDURE Recalculate (e: E; window: DPSWindow.T) =
 VAR width: REAL;
 VAR lineCount, line: INTEGER;
 VAR maxWidth: REAL;
 VAR c: CHAR;
  BEGIN
  lineCount := 1;
  FOR k := 0 TO Text.Length(e.text)-2 DO
    IF Text.GetChar(e.text,k)='\n' THEN lineCount := lineCount + 1; END;
    END;
  e.lines := NEW (REF ARRAY OF TEXT, lineCount);
  FOR k := 0 TO lineCount-1 DO e.lines[k] := ""; END;
  line := 0;
  FOR k := 0 TO Text.Length(e.text)-1 DO
    c := Text.GetChar(e.text,k);
    IF c='\n' THEN line := line + 1;
     ELSE e.lines[line] := e.lines[line] & Text.FromChar(c);
      END;
    END;
  maxWidth := 0.0;
  FOR k := 0 TO lineCount-1 DO
    e.lines[k] := DPS.EscapeText(e.lines[k]);
    width := DPS.TextWidth (e.lines[k], window, "ButtonDLEFont");
    IF width > maxWidth THEN maxWidth := width; END;
    END;
  e.box.high.x := e.box.low.x + xMargin + maxWidth + xMargin;
  e.box.high.y := e.box.low.y + yMargin + fontHeight + yMargin
   + FLOAT(lineCount-1) * lineEscapement;
  END Recalculate;

PROCEDURE Mouse (e: E; window: DPSWindow.T; event: DPS.MouseEvent): BOOLEAN =
 VAR in: BOOLEAN;
 VAR affected: DisplayList.E;
  BEGIN
  Init (e, window);
  in := DPS.PlaceIsInBox (event.place, e.box);
  IF in THEN
    IF event.clickType = DPS.ClickType.FirstDown THEN
      affected := e.MoveToLast();
      IF affected#NIL THEN affected.Dirty (affected.box, affected); END;
      END;
    END;
  RETURN in;
  END Mouse;

PROCEDURE Replace (e: E; text: TEXT; window: DPSWindow.T := NIL) =
 VAR oldBox: DPS.Box;
  BEGIN
  e.text := text;
  IF window # NIL THEN (* Else better be before initialization. *)
    oldBox := e.box;
    Recalculate (e, window);
    window.Dirty ( DPS.BoxUnion (oldBox, e.box), NIL );
    END;
  END Replace;

  BEGIN
  END SimpleTextDLE.