Coverage for gws-app/gws/base/legend/core.py: 94%

34 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-05 13:35 +0200

1"""Base legend object.""" 

2 

3from typing import Optional 

4 

5import gws 

6import gws.lib.image 

7 

8 

9class Props(gws.Props): 

10 type: str 

11 

12 

13class Config(gws.ConfigWithAccess): 

14 """Layer legend confuguration.""" 

15 

16 cacheMaxAge: gws.Duration = '1d' 

17 """How long legend images from remote sources are cached.""" 

18 options: Optional[dict] 

19 """Provider-specific legend options.""" 

20 

21 

22class Object(gws.Legend): 

23 """Base legend object. 

24 

25 Reads the common ``cacheMaxAge`` and ``options`` settings. Subclasses 

26 implement ``render`` and can stack several legend images into one with 

27 ``combine_outputs``. 

28 """ 

29 

30 cacheMaxAge: int 

31 """How long legend images from remote sources are cached, in seconds.""" 

32 options: dict 

33 """Provider-specific legend options.""" 

34 

35 def configure(self): 

36 self.options = self.cfg('options', default={}) 

37 self.cacheMaxAge = self.cfg('cacheMaxAge', default=3600 * 24) 

38 

39 

40def combine_outputs(lro_list: list[gws.LegendRenderOutput], options: dict = None) -> Optional[gws.LegendRenderOutput]: 

41 """Combine several legend outputs into one image. 

42 

43 The images are stacked vertically, aligned to the left. Outputs without an 

44 image are skipped. 

45 

46 Args: 

47 lro_list: Legend outputs to combine; ``None`` entries are allowed. 

48 options: Legend options, currently unused. 

49 

50 Returns: 

51 A new legend output with the combined image, or ``None`` if there are 

52 no images. 

53 """ 

54 imgs = [] 

55 for lro in lro_list: 

56 if lro and lro.image: 

57 imgs.append(lro.image) 

58 if not imgs: 

59 return 

60 img = _combine_images(imgs, options) 

61 return gws.LegendRenderOutput(image=img, size=img.size()) 

62 

63 

64def _combine_images(images: list[gws.Image], options: dict = None): 

65 """Combine images into one.""" 

66 return _combine_vertically(images) 

67 

68 

69def _combine_vertically(images: list[gws.Image]): 

70 """Stack images vertically on a transparent canvas.""" 

71 ws = [img.size()[0] for img in images] 

72 hs = [img.size()[1] for img in images] 

73 

74 comp = gws.lib.image.from_size((max(ws), sum(hs))) 

75 y = 0 

76 for img in images: 

77 comp.paste(img, (0, y)) 

78 y += img.size()[1] 

79 

80 return comp