WMImageGrid.Mod 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. (*Author: Stephan Koster; Purpose: Components to display multiple images arranged in a grid*)
  2. MODULE WMImageGrid;
  3. IMPORT WMWindowManager, Graphics:=WMGraphics, Raster, Messages:=WMMessages, Rectangles:=WMRectangles;
  4. TYPE Message=Messages.Message;
  5. TYPE Rectangle=Rectangles.Rectangle;
  6. TYPE Grid=ARRAY OF ARRAY OF Graphics.Image;
  7. TYPE GridWindow* = OBJECT(WMWindowManager.Window)
  8. VAR
  9. imgs*: POINTER TO Grid;
  10. background*: Graphics.Image;
  11. canvas* : Graphics.BufferCanvas;
  12. canvasGen-: Graphics.CanvasGenerator;
  13. pointerThreshold*,
  14. maxInterpolation* : LONGINT; (* allows limiting the interpolation degree on Draw *)
  15. totalW, totalH: LONGINT;
  16. gap: LONGINT;
  17. PROCEDURE &Init1*( CONST Ws, Hs: ARRAY OF LONGINT; alpha : BOOLEAN);
  18. VAR
  19. i,j: LONGINT;
  20. rm: Raster.Mode;
  21. pix: Raster.Pixel;
  22. BEGIN
  23. gap:=10;
  24. FOR i:=0 TO LEN(Ws,0)-1 DO
  25. ASSERT(Ws[i]>0);
  26. totalW:=totalW+Ws[i];
  27. END;
  28. totalW:=totalW+gap*(LEN(Ws,0)-1);
  29. FOR i:=0 TO LEN(Hs,0)-1 DO
  30. ASSERT(Hs[i]>0);
  31. totalH:=totalH+Hs[i];
  32. END;
  33. totalH:=totalH+gap*(LEN(Hs,0)-1);
  34. Init(totalW, totalH, alpha); (*parent constructor*)
  35. NEW(imgs,LEN(Ws,0),LEN(Hs,0));
  36. FOR i:=0 TO LEN(Ws,0)-1 DO
  37. FOR j:=0 TO LEN(Hs,0)-1 DO
  38. NEW(imgs[i,j]);
  39. IF alpha THEN Raster.Create(imgs[i,j], Ws[i], Hs[j], Raster.BGRA8888) ELSE Raster.Create(imgs[i,j], Ws[i], Hs[j], WMWindowManager.format) END;
  40. END
  41. END;
  42. NEW(background);
  43. IF alpha THEN Raster.Create(background, totalW, totalH, Raster.BGRA8888) ELSE Raster.Create(background, totalW, totalH, WMWindowManager.format) END;
  44. Raster.InitMode(rm, Raster.srcOverDst);
  45. Raster.SetRGBA(pix, 0,0,0,255);
  46. Raster.Fill(background, 0,0, totalW,totalH,pix, rm);
  47. SetCanvasGenerator(Graphics.GenCanvas);
  48. pointerThreshold := 1; (* invisible pixels are treated as invisible *)
  49. maxInterpolation := Graphics.ScaleBilinear;
  50. END Init1;
  51. PROCEDURE SetCanvasGenerator*(canvasGen:Graphics.CanvasGenerator);
  52. BEGIN{EXCLUSIVE}
  53. SELF.canvasGen:=canvasGen; IF background # NIL THEN canvas:=canvasGen(background); END;
  54. IF manager # NIL THEN manager.AddVisibleDirty(SELF, bounds) END
  55. END SetCanvasGenerator;
  56. PROCEDURE IsHit(x, y : LONGINT) : BOOLEAN;
  57. VAR w, h : LONGINT; fx, fy : REAL;
  58. BEGIN
  59. w := GetWidth(); h := GetHeight();
  60. IF (w > 0) & (h > 0) & ((w # totalW) OR (h # totalH)) THEN
  61. fx := totalW/ w;
  62. fy := totalH/ h;
  63. RETURN Graphics.IsBitmapHit(ENTIER(x * fx), ENTIER(y * fy), pointerThreshold, background)
  64. ELSE RETURN Graphics.IsBitmapHit(x, y, pointerThreshold, background)
  65. END
  66. END IsHit;
  67. PROCEDURE Draw*(canvas : Graphics.Canvas; w, h, q : LONGINT);
  68. VAR
  69. mode: LONGINT;
  70. isScaled: BOOLEAN;
  71. i,j: LONGINT;
  72. x,y: LONGINT;
  73. PROCEDURE DrawSingle(CONST img: Graphics.Image; offX,offY: LONGINT; isScaled: BOOLEAN; mode: LONGINT);
  74. VAR
  75. wscaled,hscaled: LONGINT;
  76. BEGIN
  77. IF img # NIL THEN
  78. IF ~isScaled THEN
  79. canvas.DrawImage(offX,offY,img, mode);
  80. ELSE
  81. offX:=offX*w DIV totalW; (*these are not pixel perfect, but I can't think of anything better*)
  82. offY:=offY*h DIV totalH;
  83. wscaled:=img.width*w DIV totalW;
  84. hscaled:=img.height*h DIV totalH;
  85. canvas.ScaleImage(img, Rectangles.MakeRect(0, 0, img.width, img.height), Rectangles.MakeRect(offX,offY, offX+wscaled, offY+hscaled), mode, MIN(q,maxInterpolation));
  86. END
  87. END;
  88. END DrawSingle;
  89. BEGIN
  90. IF useAlpha THEN
  91. mode:=Graphics.ModeSrcOverDst;
  92. ELSE
  93. mode:=Graphics.ModeCopy;
  94. END;
  95. isScaled:=~((w = totalW) & (h = totalH));
  96. IF reduceQuality THEN q := 0 END;
  97. DrawSingle(background, 0,0, isScaled, mode);
  98. x:=0;
  99. FOR i:=0 TO LEN(imgs,0)-1 DO
  100. y:=0;
  101. FOR j:=0 TO LEN(imgs,1)-1 DO
  102. DrawSingle(imgs[i,j], x,y, isScaled,mode);
  103. y:=y+imgs[0,j].height+gap;
  104. END;
  105. x:=x+imgs[i,0].width+gap;
  106. END;
  107. INC(timestamp);
  108. END Draw;
  109. PROCEDURE Invalidate*(rect : Rectangle);
  110. VAR w, h : LONGINT; fx, fy : REAL;
  111. BEGIN
  112. w := GetWidth(); h := GetHeight();
  113. IF (w > 0) & (h > 0) & ((w # totalW) OR (h # totalH)) THEN
  114. fx := w / totalW; fy := h / totalH;
  115. rect.l := ENTIER(rect.l * fx); rect.t := ENTIER(rect.t * fy);
  116. rect.r := ENTIER(rect.r * fx + 0.5); rect.b := ENTIER(rect.b * fy + 0.5)
  117. END;
  118. Invalidate^(rect)
  119. END Invalidate;
  120. PROCEDURE Handle*(VAR m : Message);
  121. VAR w, h : LONGINT; fx, fy : REAL;
  122. BEGIN
  123. w := GetWidth(); h := GetHeight();
  124. IF (w > 0) & (h > 0) & ((w # totalW) OR (h # totalH)) & (m.msgType = Messages.MsgPointer) THEN
  125. m.x := m.x-bounds.l; m.y := m.y-bounds.t;
  126. fx := totalW/ w;
  127. fy := totalH/ h;
  128. m.x := ENTIER(m.x * fx); m.y := ENTIER(m.y * fy);
  129. m.x := m.x + bounds.l; m.y := m.y+bounds.l;
  130. END;
  131. Handle^(m)
  132. END Handle;
  133. END GridWindow;
  134. PROCEDURE Test*();
  135. VAR
  136. w: GridWindow;
  137. Ws,Hs: ARRAY 3 OF LONGINT;
  138. i: LONGINT;
  139. rm: Raster.Mode;
  140. pix: Raster.Pixel;
  141. BEGIN
  142. FOR i:=0 TO 2 DO
  143. Ws[i]:=100*i+30;
  144. Hs[i]:=20+200*i;
  145. END;
  146. NEW(w,Ws,Hs, TRUE);
  147. Raster.InitMode(rm, Raster.srcOverDst);
  148. Raster.SetRGBA(pix, 255,0,0,255);
  149. Raster.Fill(w.imgs[0,0], 0,0, Ws[0],Hs[0],pix, rm);
  150. Raster.SetRGBA(pix, 0,255,0,255);
  151. Raster.Fill(w.imgs[1,1], 0,0, Ws[1],Hs[1],pix, rm);
  152. Raster.SetRGBA(pix, 0,0,255,255);
  153. Raster.Fill(w.imgs[2,2], 0,0, Ws[2],Hs[2],pix, rm);
  154. WMWindowManager.DefaultAddWindow(w);
  155. END Test;
  156. END WMImageGrid.
  157. SystemTools.FreeDownTo ImageGrid~
  158. ImageGrid.Test~