Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
HiddenText.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Frameworks_Led_HiddenText_h_
5#define _Stroika_Frameworks_Led_HiddenText_h_ 1
6
7#include "Stroika/Frameworks/StroikaPreComp.h"
8
9/*
10@MODULE: HiddenText
11@DESCRIPTION:
12 <p>This module provides generic support for keeping arbitrary ranges of text hidden within
13 a Led buffer, but making it available for later display.</p>.
14 */
15
16#include "StandardStyledTextImager.h" //only for template used in light-underline-xxxx - maybe move to WP file... so dont need this include here!
17#include "StyledTextImager.h"
18#include "Support.h"
19#include "TextInteractor.h"
20
21namespace Stroika::Frameworks::Led {
22
23 /**
24 * <p>HidableTextMarkerOwner is a @'MarkerOwner' class, collecting together a set of
25 * @'HidableTextMarkerOwner::HidableTextMarker' elements. Each of these hidden-text elements can contain
26 * either currently hidden text, or text which could potentially be hidden.</p>
27 * <p>Note that not all @'HidableTextMarkerOwner::HidableTextMarker' elements need to share the same
28 * 'hidden' / 'shown' state. Some can be hidden while others shown. And markers of different subclasses of
29 * @'HidableTextMarkerOwner::HidableTextMarker' can be collected together in a single, or in multiple
30 * @'HidableTextMarkerOwner's.</p>
31 * <p>See @'HidableTextMarkerOwner::HidableTextMarker' for more details, and subclasses.</p>
32 * <p><em>Implemenation Note:</em><br>
33 * I considered implementing this using a map<> for its red-black tree implementation. That might turn out to
34 * be faster if you have lots of hidden text. But the APIs STL provides you when you try todo this are not very friendly.
35 * I battled them for a while (you must make a map with a second bogus field, and then everywhere try to say 'first' after
36 * you access the interator - and thats not so bad in MY code - but when I use the builtin STL helpers - its more of a pain, and
37 * then the lookup - find routine was a real pain - cuz I don't want to lookup by Marker* - but by POSITION).</p>
38 */
40 private:
41 using inherited = MarkerOwner;
42
43 public:
44 HidableTextMarkerOwner (TextStore& textStore);
45 virtual ~HidableTextMarkerOwner ();
46
47 public:
48 virtual void HideAll ();
49 virtual void HideAll (size_t from, size_t to);
50 virtual void ShowAll ();
51 virtual void ShowAll (size_t from, size_t to);
52
53 public:
54 virtual void MakeRegionHidable (size_t from, size_t to);
55 virtual void MakeRegionUnHidable (size_t from, size_t to);
56
57 public:
58 nonvirtual DiscontiguousRun<bool> GetHidableRegions () const;
59 nonvirtual DiscontiguousRun<bool> GetHidableRegions (size_t from, size_t to) const;
60
61 public:
62 nonvirtual bool GetHidableRegionsContiguous (size_t from, size_t to, bool hidden) const;
63
64 public:
65 nonvirtual shared_ptr<FlavorPackageInternalizer> GetInternalizer () const;
66 nonvirtual void SetInternalizer (const shared_ptr<FlavorPackageInternalizer>& i);
67
68 private:
69 shared_ptr<FlavorPackageInternalizer> fInternalizer;
70
71 public:
72 nonvirtual shared_ptr<FlavorPackageExternalizer> GetExternalizer () const;
73 nonvirtual void SetExternalizer (const shared_ptr<FlavorPackageExternalizer>& e);
74
75 private:
76 shared_ptr<FlavorPackageExternalizer> fExternalizer;
77
78 protected:
79 class HidableTextMarker;
80 class FontSpecHidableTextMarker;
82
83 // called by 'HidableTextMarker's to compute their 'saved data'
84 protected:
85 virtual void CollapseMarker (HidableTextMarker* m);
86 virtual void ReifyMarker (HidableTextMarker* m);
87
88 protected:
89 virtual HidableTextMarker* MakeHidableTextMarker ();
90
91 public:
92 virtual TextStore* PeekAtTextStore () const override;
93
94 public:
95 virtual void AboutToUpdateText (const UpdateInfo& updateInfo) override;
96 virtual void DidUpdateText (const UpdateInfo& updateInfo) noexcept override;
97
98 private:
99 TextStore& fTextStore;
100 mutable MarkerMortuary<HidableTextMarker> fMarkersToBeDeleted;
101
102 protected:
103 using MarkerList = vector<HidableTextMarker*>;
104
105 protected:
106 nonvirtual MarkerList CollectAllInRange (size_t from, size_t to) const;
107 nonvirtual MarkerList CollectAllInRange_OrSurroundings (size_t from, size_t to) const;
108
109 public:
110 nonvirtual void Invariant () const;
111
112#if qStroika_Foundation_Debug_AssertionsChecked
113 protected:
114 virtual void Invariant_ () const;
115#endif
116
117 public:
118 friend class HidableTextMarker;
119 };
120
121 /**
122 */
123 class HidableTextMarkerOwner::HidableTextMarker : public StyleMarker {
124 private:
125 using inherited = StyleMarker;
126
127 public:
128 HidableTextMarker ();
129
130 public:
131 nonvirtual void Hide ();
132 nonvirtual void Show ();
133 nonvirtual bool IsShown () const;
134
135 protected:
136 nonvirtual HidableTextMarkerOwner& GetOwner () const;
137
138 private:
139 bool fShown;
140
141 public:
142 friend class HidableTextMarkerOwner;
143 };
144
145 /*
146 @CLASS: HidableTextMarkerHelper<BASECLASS>
147 @BASES: BASECLASS
148 @DESCRIPTION: <p>This class can be used with any 'BASECLASS' of subtype @'StyledTextImager::StyleMarker' and which also has
149 an IsShown () method. Really it should most probably just be used with subclasses of @'HidableTextMarkerOwner::HidableTextMarker'.
150 Note that the 'BASECLASS' should also be a CONCRETE base class - or at least have already defined its DrawSegment, etc methods. Basically
151 all this helper does is choose whether or not to invoke those inherited DrawSegment etc methods or to return fake zero-size versions.
152 </p>
153 */
154 template <typename BASECLASS>
155 class HidableTextMarkerHelper : public BASECLASS {
156 private:
157 using inherited = BASECLASS;
158
159 public:
160 HidableTextMarkerHelper () = default;
161
162 public:
163 virtual int GetPriority () const override;
164
165#if qStroika_Frameworks_Led_SupportGDI
166 protected:
167 virtual void DrawSegment (const StyledTextImager* imager, const StyleRunElement& runElement, Tablet* tablet, size_t from, size_t to,
168 const TextLayoutBlock& text, const Led_Rect& drawInto, const Led_Rect& /*invalidRect*/,
169 CoordinateType useBaseLine, DistanceType* pixelsDrawn) override;
170 virtual void MeasureSegmentWidth (const StyledTextImager* imager, const StyleRunElement& runElement, size_t from, size_t to,
171 const Led_tChar* text, DistanceType* distanceResults) const override;
172 virtual DistanceType MeasureSegmentHeight (const StyledTextImager* imager, const StyleRunElement& runElement, size_t from, size_t to) const override;
173
174 virtual DistanceType MeasureSegmentBaseLine (const StyledTextImager* imager, const StyleRunElement& runElement, size_t from, size_t to) const override;
175#endif
176 };
177
178 /**
179 * <p>Adds a light dashed underline to the given region. One advantage of
180 * this over @'HidableTextMarkerOwner::FontSpecHidableTextMarker' is that
181 * it works well with other embeddings and display markers, cuz it lets them
182 * do their drawing, and simply adds the underline.</p>
183 */
185 : public HidableTextMarkerHelper<SimpleStyleMarkerWithLightUnderline<SimpleStyleMarkerByIncrementalFontSpec<
186 SimpleStyleMarkerByIncrementalFontSpecStandardStyleMarkerHelper<SimpleStyleMarkerWithExtraDraw<HidableTextMarkerOwner::HidableTextMarker>>>>>,
187 public Foundation::Memory::UseBlockAllocationIfAppropriate<LightUnderlineHidableTextMarker> {
188 private:
189 using inherited = HidableTextMarkerHelper<SimpleStyleMarkerWithLightUnderline<SimpleStyleMarkerByIncrementalFontSpec<
190 SimpleStyleMarkerByIncrementalFontSpecStandardStyleMarkerHelper<SimpleStyleMarkerWithExtraDraw<HidableTextMarkerOwner::HidableTextMarker>>>>>;
191
192 public:
193 LightUnderlineHidableTextMarker (const IncrementalFontSpecification& fsp = IncrementalFontSpecification ());
194
195 virtual Color GetUnderlineBaseColor () const override;
196 };
197
198 /*
199 @CLASS: HidableTextMarkerOwner::FontSpecHidableTextMarker
200 @BASES: @'SimpleStyleMarkerByFontSpec<BASECLASS>, where BASECLASS = @'HidableTextMarkerHelper<BASECLASS>' where BASECLASS = @'HidableTextMarkerOwner::HidableTextMarker'
201 @DESCRIPTION: <p>Adds the argument style specification to the selected text. Smart enough to handle style overlaps with some kinds of
202 style markers (most importantly - @'StandardStyledTextImager::StandardStyleMarker').</p>
203 <p>May have to also add embedding support to this. And may want to move this functionality out of here, and into
204 some other helper file, and just USE the functionality here.</p>
205 <p>See also @'HidableTextMarkerOwner::LightUnderlineHidableTextMarker'.</p>
206 */
207 class HidableTextMarkerOwner::FontSpecHidableTextMarker
208 : public HidableTextMarkerHelper<SimpleStyleMarkerByFontSpec<HidableTextMarkerOwner::HidableTextMarker>>,
209 public Foundation::Memory::UseBlockAllocationIfAppropriate<FontSpecHidableTextMarker> {
210 private:
211 using inherited = HidableTextMarkerHelper<SimpleStyleMarkerByFontSpec<HidableTextMarkerOwner::HidableTextMarker>>;
212
213 public:
214 FontSpecHidableTextMarker (const IncrementalFontSpecification& styleInfo);
215
216#if qStroika_Frameworks_Led_SupportGDI
217 protected:
218 virtual FontSpecification MakeFontSpec (const StyledTextImager* imager, const StyleRunElement& runElement) const override;
219#endif
220
221 public:
222 IncrementalFontSpecification fFontSpecification;
223 };
224
225 /**
226 * UniformHidableTextMarkerOwner is a @'HidableTextMarkerOwner' class, which has a notion of
227 * whether or not <em>all</em> the hidden text markers are hidden or not. You can manually change the hidden
228 * state of particular markers - if you wish (via @'HidableTextMarkerOwner::HideAll ()' commands with a from/to range).</p>
229 * <p>But the default behavior is that all the markers share this hidden or not hidden state, and NEWLY created
230 * 'hiding' markers inherit this state.</p>
231 */
233 private:
235
236 public:
237 UniformHidableTextMarkerOwner (TextStore& textStore);
238
239 public:
240 virtual void HideAll () override;
241 virtual void ShowAll () override;
242
243 public:
244 nonvirtual bool IsHidden () const;
245
246 public:
247 virtual void MakeRegionHidable (size_t from, size_t to) override;
248
249 private:
250 bool fHidden{false};
251 };
252
253 /**
254 * <p>A @'UniformHidableTextMarkerOwner' where you can specify (simply) a color for the
255 * hidable text markers (when they are shown).</p>
256 */
258 private:
260
261 public:
262 ColoredUniformHidableTextMarkerOwner (TextStore& textStore);
263
264 public:
265 nonvirtual Color GetColor () const;
266 nonvirtual void SetColor (const Color& color);
267 nonvirtual bool GetColored () const;
268 nonvirtual void SetColored (bool colored);
269
270 protected:
271 nonvirtual void FixupSubMarkers ();
272
273 protected:
274 virtual HidableTextMarker* MakeHidableTextMarker () override;
275
276 private:
277 Color fColor;
278 bool fColored;
279 };
280
281}
282
283/*
284 ********************************************************************************
285 ***************************** Implementation Details ***************************
286 ********************************************************************************
287 */
288#include "HiddenText.inl"
289
290#endif /*_Stroika_Frameworks_Led_HiddenText_h_*/
conditional_t< qStroika_Foundation_Memory_PreferBlockAllocation and andTrueCheck, BlockAllocationUseHelper< T >, Common::Empty > UseBlockAllocationIfAppropriate
Use this to enable block allocation for a particular class. Beware of subclassing.