Loading...
Searching...
No Matches
AlignSVG.h
1/*
2
3MIT License
4
5Copyright (c) 2023 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31/*
32 * TreeSVG.h
33 *
34 * Created on: Nov, 2024
35 * Author: mpeura
36 */
37
38#ifndef DRAIN_ALIGN_SVG
39#define DRAIN_ALIGN_SVG
40
41#include <drain/Enum.h>
42#include <string>
43
44namespace drain {
45
46namespace image {
47
48
50struct AlignBase {
51
52public:
53
55 enum Pos {
56 UNDEFINED_POS = 0,
57 MIN = 1, // LEFT (if HORZ) or TOP (when VERT) 0b01010101,
58 MAX = 2, // RIGHT (if HORZ) or BOTTOM (when VERT) 0b10101010,
59 MID = 3, // 0b11111111,
60 FILL = 4,
61 // ABSOLUTE?
62 };
63
64 enum Axis {
65 // Index, must contain 0 and 1 for HORZ and VERT
66 HORZ = 0, // 0b00110011,
67 VERT = 1, // b11001100,
68 UNDEFINED_AXIS = 2,
69 };
70
71
73 /*
74 enum Axis {
75 // Index, must contain 0 and 1 for HORZ and VERT
76 UNDEFINED_AXIS = 0,
77 HORZ = 1, // 0b00110011,
78 VERT = 2, // b11001100,
79 };
80 */
81
82 static inline
83 Axis flip(Axis axis){
84 switch (axis){
85 case HORZ:
86 return VERT;
87 case VERT:
88 return HORZ;
89 default:
90 return UNDEFINED_AXIS;
91 }
92 };
93
94 //typedef drain::Enum<Coord>::dict_t pos_dict_t;
95
96 static inline
98 switch (pos){
99 case MAX:
100 return MIN;
101 case MIN:
102 return MAX;
103 case MID:
104 case FILL:
105 case UNDEFINED_POS:
106 default:
107 return pos;
108 }
109 };
110
111};
112
113
114// template <> const drain::Enum<AlignBase::Axis>::dict_t drain::Enum<AlignBase::Axis>::dict;
115DRAIN_ENUM_DICT(AlignBase::Axis);
116DRAIN_ENUM_OSTREAM(AlignBase::Axis);
117
118// template <>const drain::Enum<AlignBase::Pos>::dict_t drain::Enum<AlignBase::Pos>::dict;
119DRAIN_ENUM_DICT(AlignBase::Pos);
120DRAIN_ENUM_OSTREAM(AlignBase::Pos);
121
122
124
135template <typename AX = AlignBase::Axis, AlignBase::Axis A = AlignBase::Axis::UNDEFINED_AXIS> //, typename POS = AlignBase::Pos> // , Align::Coord POS = Align::Coord::UNDEFINED_POS>
136struct Alignment {
137
138 // Align::Axis
139 AX axis; // = V; // compiler error if different type?
140
141 //AlignBase::Pos pos
142 AlignBase::Pos pos = AlignBase::Pos::UNDEFINED_POS; // or middle?
143 //POS pos = AlignBase::Pos::UNDEFINED_POS; // or middle?
144
146 inline
147 Alignment(AlignBase::Pos pos = AlignBase::Pos::UNDEFINED_POS) : axis(A), pos(pos){
148 }
149
151 inline
152 Alignment(const Alignment & ac) : axis(ac.axis), pos(ac.pos){
153 }
154
155
156 inline
157 Alignment(AlignBase::Axis axis, AlignBase::Pos pos = AlignBase::Pos::UNDEFINED_POS): axis(axis), pos(pos){
158 }
159
160 template <typename AX2, AlignBase::Axis A2>
161 inline
162 Alignment(const Alignment<AX2,A2> & align) : pos(align.pos){ // axis(ac.axis),
163 axis = align.axis; // error if const
164 }
165
167 inline virtual
169
170
171 inline
172 const AlignBase::Axis & get(const AlignBase::Axis & defaultValue) const {
173 if (axis != AlignBase::Axis::UNDEFINED_AXIS){
174 return axis;
175 }
176 else {
177 return defaultValue;
178 }
179 }
180
181 inline
182 const AlignBase::Pos & get(const AlignBase::Pos & defaultValue) const {
183 if (pos != AlignBase::Pos::UNDEFINED_POS){
184 return pos;
185 }
186 else {
187 return defaultValue;
188 }
189 }
190
191
192 virtual inline
193 void reset(){
194 axis = AlignBase::Axis::UNDEFINED_AXIS;
195 pos = AlignBase::Pos::UNDEFINED_POS;
196 }
197
198
199 template <typename AX2, AlignBase::Axis A2>
200 inline
201 bool operator==(const Alignment<AX2,A2> & align) const {
202 return (align.axis == axis) && (align.pos == pos);
203 // return compare(ad) == 0;
204 }
205
206 /*
207 inline
208 Alignment<AX,A> & operator=(Alignment<AX,A> & align){
209 // axis = align.axis;
210 pos = align.pos;
211 return *this;
212 }
213 */
214
215
216
217
218};
219
220
221
222template <typename AX, AlignBase::Axis V>
223inline
224std::ostream & operator<<(std::ostream &ostr, const Alignment<AX,V> & align){
225 //return ostr << align.axis << '_' << align.pos; // enums resolved above
226 return ostr << align.axis << '_' << align.pos;
227}
228
230
231 enum Topol {
232 INSIDE = 0,
233 OUTSIDE = 1,
234 UNDEFINED_TOPOL = 2,
235 };
236
237
238};
239
240
242
255template <typename AX = AlignBase::Axis, AlignBase::Axis A = AlignBase::Axis::UNDEFINED_AXIS> // , Align::Coord POS = Align::Coord::UNDEFINED_POS>
256struct CompleteAlignment : public Alignment<AX,A> {
257
258 MutualAlign::Topol topol = MutualAlign::Topol::INSIDE; // or undef?
259
261 template <class ...TT>
262 CompleteAlignment(const TT... args) : Alignment<AX,A>() {
263 set(args...);
264 }
265
266 inline
268
269 virtual inline
270 bool isSet() const {
271 return (this->axis != AlignBase::Axis::UNDEFINED_AXIS) &&
272 (this->pos != AlignBase::Pos::UNDEFINED_POS) &&
273 (topol != MutualAlign::Topol::UNDEFINED_TOPOL);
274 // return Alignment<AX,A>::isSet() && (topol != MutualAlign::Topol::UNDEFINED_TOPOL);
275 }
276
277 inline
278 const MutualAlign::Topol & getOrDefault(const MutualAlign::Topol & defaultValue) const {
279 if (topol != MutualAlign::Topol::UNDEFINED_TOPOL){
280 return topol;
281 }
282 else {
283 return defaultValue;
284 }
285 }
286
287
288 // Sets all members to UNDEFINED state.
289 virtual inline
290 void reset(){
291 Alignment<AX,A>::reset();
292 topol = MutualAlign::Topol::UNDEFINED_TOPOL;
293 // this->updateAlign();
294 }
295
296
297 template <typename AX2, AlignBase::Axis A2, class ...TT>
298 void set(const Alignment<AX2,A2> & align, const TT... args){
299 this->axis = align.axis;
300 this->pos = align.pos;
301 set(args...);
302 }
303
304 template <class ...TT>
305 void set(MutualAlign::Topol topol, const TT... args){
306 this->topol = topol;
307 set(args...);
308 }
309
310 template <class ...TT>
311 void set(AlignBase::Axis axis, const TT... args){
312 this->axis = axis;
313 set(args...);
314 }
315
316 template <class ...TT>
317 void set(AlignBase::Pos coord, const TT... args){
318 this->pos = coord;
319 set(args...);
320 }
321
322 template <class ...TT>
323 void set(const std::string & key, const TT... args){
324 if (Enum<MutualAlign::Topol>::setValue(key, topol)){
325 // ok
326 }
327 else if (Enum<Alignment<> >::setValue(key, *this)){ // RIGHT or?
328 // ok
329 }
330 else if (Enum<AlignBase::Axis>::setValue(key, this->axis)){
331 // ok
332 }
333 else if (Enum<AlignBase::Pos>::setValue(key, this->pos)){
334 // ok
335 }
336 else {
337 // Advice: keys
338 throw std::runtime_error(drain::StringBuilder<>("key '", key, "' not found. Appeared in: ", args...));
339 }
340
341 set(args...);
342 }
343
344 template <class ...TT>
345 void set(const char *key, const TT... args){
346 set(std::string(key), args...);
347 }
348
349
350protected:
351
352 inline
353 void set(){
354 // this->updateAlign(); // ok?
355 }
356
357};
358
359
360//struct Alignment2;
361
363
369struct AlignSVG { // : protected Align {
370
371
372 virtual
373 ~AlignSVG(){};
374
376
378 static
380
382 static
384
386 static
388
390 static
392
393 static
394 const HorzAlign UNDEFINED_HORZ;
395
396 // ----------------------
397
399
401 static
403
405 static
407
409 static
411
413 static
415
416 static
417 const VertAlign UNDEFINED_VERT;
418
419
420 enum Owner {
421 OBJECT = 0, // 0b00001111,
422 ANCHOR = 1, // 0b11110000,
423 };
424
425
426
427
429 /*
430 * Notice that for an alignment to be complete, this function should be called twice:
431 * setting partial alignment for both owner=OBJECT and owner=ANCHOR .
432 *
433 * \tparam OBJ - enum type \c Owner or string
434 * \tparam A - enum type \c Axis or string
435 * \tparam V - enum type \c Alignment or string
436 * \param pos - enum value \c OBJ or \c REF
437 * \param axis - enum value \c HORZ or \c VERT
438 * \param value - enum value \c MAX , \c MID , or \c MIN (or string)
439 */
440 template <typename OBJ, typename A, typename V>
441 inline // in problems, rename this function, ie. remove polymorphism
442 void setAlign(const OBJ & owner, const A & axis, const V &value){
443 modifyAlign(owner, axis, value);
444 updateAlign();
445 }
446
448
457 inline
458 void setAlign(const AlignBase::Axis & axis, const AlignBase::Pos & pos, MutualAlign::Topol topol=MutualAlign::Topol::INSIDE){
459 if (pos != AlignBase::FILL){
460 modifyAlign(ANCHOR, axis, pos);
461 }
462 modifyAlign(OBJECT, axis, (topol==MutualAlign::INSIDE) ? pos : AlignBase::flip(pos));
463 updateAlign();
464 }
465
467 /*
468 * Template supports empty arg list.
469 *
470 * \tparam T - enum type \c Topol or string
471 * \tparam AX - axis enum type: Axis or const Axis
472 * \tparam A - axis enum value: HORZ, VERT or UNDEFINED_AXIS
473 * \param align - \c HorzAlign or \c VertAlign
474 */
475 template <typename ...T, typename AX, AlignBase::Axis A>
476 void setAlign(const Alignment<AX,A> & align, const T... args){
477 if (align.pos == AlignBase::FILL){
478 // Makes sense only for OBJECT, as it will be changed (and ANCHOR is never unchanged).
479 setAlign(AlignSVG::OBJECT, align.axis, align.pos);
480 }
481 else {
482 setAlign(align.axis, align.pos, args...);
483 }
484 }
485
486 // Convenience: set both horz and vert alignments (INSIDE)
487 /*
488 */
489 template <typename AX1, AlignBase::Axis A1, typename AX2, AlignBase::Axis A2>
490 void setAlign(const Alignment<AX1,A1> & align1, const Alignment<AX2,A2> & align2){
491 setAlign(align1.axis, align1.pos, MutualAlign::Topol::INSIDE);
492 setAlign(align2.axis, align2.pos, MutualAlign::Topol::INSIDE);
493 }
494
495 // Convenience: set both horz and vert alignments (INSIDE)
496 /*
497 */
498 template <typename AX1, AlignBase::Axis A1> // , typename AX2, AlignBase::Axis A2>
499 void setAlign(const CompleteAlignment<AX1,A1> & align1){
500 setAlign(align1.axis, align1.pos, align1.topol);
501 //setAlign(align2.axis, align2.pos, MutualAlign::Topol::INSIDE);
502 }
503
504
506 template <typename AX, AlignBase::Axis A>
507 void setAlign(const Alignment<AX,A> & align1, const Alignment<AX,A> & align2);
508
509
511 /*
512 * \tparam T - enum type \c Topol or string: \c INSIDE or \c OUTSIDE .
513 * \param align - Horizontal or vertical Alignment: \c LEFT|CENTER|RIGHT or \c TOP|MIDDLE|BOTTOM
514 * \param topol - \c INSIDE or \c OUTSIDE
515 */
516 template <typename T>
517 void setAlign(const std::string & align, const T & topol){
518 const Alignment<> & a = Enum<Alignment<> >::getValue(align, false);
519 const MutualAlign::Topol & t = Enum<MutualAlign::Topol>::getValue(topol, false);
520 //const Alignment<> & a = Enum<Alignment<> >::getValue(align, false);
521 setAlign(a.axis, a.pos, t);
522 }
523
524 /* "TODO"
525 void setAlign(const CompleteAlignment<> & align){
526 }
527 */
528
530
532 void setAlign(const std::string & align);
533 // Note: no mixed type, ANCHOR:LEFT
534
536 bool isAligned() const;
537
538 void resetAlign();
539
540 void swapAlign(AlignSVG & align);
541
543 /*
544 * \tparam P - enum type Owner \c REF or \c OBJ , or respective string.
545 * \tparam A - enum type axis_t \c HORZ or \c VERT , or respective string.
546 * \param pos - target object \c OBJ or referred anchor object \c REF
547 * \param axis - horizontal \c HORZ or vertical \c AXIS .
548 */
549 template <typename P, typename A>
550 AlignBase::Pos & getAlignPos(const P & pos, const A & axis);
551
552
554 /*
555 * \tparam P - enum type Owner \c REF or \c OBJ , or respective string.
556 * \tparam A - enum type axis_t \c HORZ or \c VERT , or respective string.
557 * \param pos - target object \c OBJ or referred anchor object \c REF
558 * \param axis - horizontal \c HORZ or vertical \c AXIS .
559 *
560 */
561 template <typename P, typename A>
562 const AlignBase::Pos & getAlignPos(const P & pos, const A & axis) const;
563
567 void confToStream(std::ostream & ostr) const;
568
569 inline
570 const std::string & getAlignStr() const {
571 return alignStr;
572 }
573
574 void swapAlign();
575 /*
577 template <typename ...TT>
578 bool isAlignSet(const TT... args) const {
579 bitvect_t v = combineAlign(args...);
580 return (alignment & v) == v;
581 }
582
583 */
584
585protected:
586
587 // Future extension
588 typedef int bitvect_t; // or int_t ?
589
590 // Future extension
591 mutable
592 bitvect_t alignment = 0;
593
594 std::string alignStr;
595
597 template <typename P, typename A, typename V>
598 void modifyAlign(const P & owner, const A & axis, const V &value){
599 getAlignPos(owner, axis) = Enum<AlignBase::Pos>::getValue(value, false);
600 }
601
602
603 void updateAlignStr();
604
605 virtual inline
606 void updateAlign(){
607 updateAlignStr();
608 };
609
610
611 typedef std::vector<AlignBase::Pos> align_vect_t;
612 typedef std::vector<align_vect_t > align_conf_t;
613
614 align_conf_t alignments = align_conf_t(2, align_vect_t(2, AlignBase::Pos::UNDEFINED_POS));
615
617
618
619};
620
621
622inline
623std::ostream & operator<<(std::ostream &ostr, const AlignSVG & align){
624 //return ostr << align.axis << '_' << align.pos; // enums resolved above
625 align.confToStream(ostr);
626 return ostr; // << "UNDER CONSTR..."; // RESOLVE!
627}
628
629
630// template <>
631// const drain::Enum<AlignSVG::Owner>::dict_t drain::Enum<AlignSVG::Owner>::dict;
632DRAIN_ENUM_DICT(AlignSVG::Owner);
633DRAIN_ENUM_OSTREAM(AlignSVG::Owner);
634
635//template <>
636//const drain::Enum<MutualAlign::Topol>::dict_t drain::Enum<MutualAlign::Topol>::dict;
637DRAIN_ENUM_DICT(MutualAlign::Topol);
638DRAIN_ENUM_OSTREAM(MutualAlign::Topol);
639
640template <>
641inline
642void AlignSVG::HorzAlign::reset(){
643 // axis = AlignBase::Axis::UNDEFINED_AXIS;
644 pos = AlignBase::Pos::UNDEFINED_POS;
645}
646
647template <>
648inline
649void AlignSVG::VertAlign::reset(){
650 // axis = AlignBase::Axis::UNDEFINED_AXIS;
651 pos = AlignBase::Pos::UNDEFINED_POS;
652}
653
654
656/*
657template <>
658const drain::Enum<AlignSVG::HorzAlign>::dict_t drain::Enum<AlignSVG::HorzAlign>::dict;
659
661template <>
662const drain::Enum<AlignSVG::VertAlign>::dict_t drain::Enum<AlignSVG::VertAlign>::dict;
663
664
666template <>
667const drain::Enum<Alignment<> >::dict_t drain::Enum<Alignment<> >::dict;
668*/
669
670DRAIN_ENUM_DICT(AlignSVG::HorzAlign);
671DRAIN_ENUM_DICT(AlignSVG::VertAlign);
672DRAIN_ENUM_DICT(Alignment<>);
673
674
675
676template <typename OBJ, typename A>
677AlignBase::Pos & AlignSVG::getAlignPos(const OBJ & owner, const A & axis){
678 const AlignSVG::Owner p = Enum<AlignSVG::Owner>::getValue(owner, false); // raise error
679 const AlignBase::Axis a = Enum<AlignBase::Axis>::getValue(axis, false); // raise error
680 return alignments[p][a];
681}
682
683template <typename OBJ, typename A>
684const AlignBase::Pos & AlignSVG::getAlignPos(const OBJ & owner, const A & axis) const {
685 const AlignSVG::Owner p = Enum<AlignSVG::Owner>::getValue(owner, false); // raise error
686 const AlignBase::Axis a = Enum<AlignBase::Axis>::getValue(axis, false); // raise error
687 return alignments[p][a];
688}
689
690
691
692
693
694template <typename AX, AlignBase::Axis A>
695std::ostream & operator<<(std::ostream &ostr, const CompleteAlignment<AX,A> & ad){
696 return ostr << ad.topol << '_' << ad.axis << ':' << ad.pos;
697}
698
699
700
701
702
703
704
705} // image::
706
707DRAIN_TYPENAME(image::AlignSVG::HorzAlign);
708DRAIN_TYPENAME(image::AlignSVG::VertAlign);
709
710} // drain::
711
712
713DRAIN_ENUM_OSTREAM(drain::image::AlignBase::Axis);
714DRAIN_ENUM_OSTREAM(drain::image::AlignBase::Pos);
715DRAIN_ENUM_OSTREAM(drain::image::AlignSVG::Owner);
716
717
718#endif // DRAIN_ALIGN_SVG_H_
719
Definition StringBuilder.h:58
Definition DataSelector.cpp:1277
A container for a static dictionary of enumeration values.
Definition Enum.h:51
static E getValue(const E &value, bool lenient=true)
Convenience for object.set(...) like commands.
Definition Enum.h:96
static bool setValue(const std::string &key, E &value)
Assign string values to an enumeration type.
Definition Enum.h:78
Low level alignment instructions.
Definition AlignSVG.h:50
static Axis flip(Axis axis)
supporting simultaneous HORZ|VERT
Definition AlignSVG.h:83
Pos
Reference position at Axis (HORZ or VERT)
Definition AlignSVG.h:55
User-friendly programming interface for alignment considering two elements.
Definition AlignSVG.h:369
static const HorzAlign LEFT
Alias for {HORZ:MIN}.
Definition AlignSVG.h:379
const AlignBase::Pos & getAlignPos(const P &pos, const A &axis) const
Return alignment setting of an object along horizontal or vertical axis .
static const VertAlign MIDDLE
Alias for {VERT:MID}.
Definition AlignSVG.h:406
void setAlign(const std::string &align, const T &topol)
High-level, user friendlier interface for setting the alignments for both OBJECT itself and its ANCHO...
Definition AlignSVG.h:517
void setAlign(const OBJ &owner, const A &axis, const V &value)
Low-level, "atomic" setter of alignment for OBJECT itself or its ANCHOR object.
Definition AlignSVG.h:442
void setAlign(const AlignBase::Axis &axis, const AlignBase::Pos &pos, MutualAlign::Topol topol=MutualAlign::Topol::INSIDE)
Set a single alignment setting. "Intermediate-level": axis and pos are given separately.
Definition AlignSVG.h:458
void confToStream(std::ostream &ostr) const
Definition AlignSVG.cpp:168
bool isAligned() const
Returns true, if any setting is set...
Definition AlignSVG.cpp:255
static const HorzAlign RIGHT
Alias for {HORZ:MAX}.
Definition AlignSVG.h:387
static const HorzAlign HORZ_FILL
Alias for {HORZ:FILL}.
Definition AlignSVG.h:391
void setAlign(const Alignment< AX, A > &align1, const Alignment< AX, A > &align2)
Compiler trap: unimplemented for two of same kind: either HorzAlign or VertAlign twice.
void modifyAlign(const P &owner, const A &axis, const V &value)
Change alignment configuration without updating the alignStr.
Definition AlignSVG.h:598
static const VertAlign VERT_FILL
Alias for {VERT:FILL}.
Definition AlignSVG.h:414
static const VertAlign BOTTOM
Alias for {VERT:MAX}.
Definition AlignSVG.h:410
void setAlign(const Alignment< AX, A > &align, const T... args)
NEW High-level, user friendlier interface for setting INSIDE the alignments for both OBJECT itself an...
Definition AlignSVG.h:476
static const HorzAlign CENTER
Alias for {HORZ:MID}.
Definition AlignSVG.h:383
AlignBase::Pos & getAlignPos(const P &pos, const A &axis)
Return alignment setting of an object along horizontal or vertical axis .
static const VertAlign TOP
Alias for {VERT:MIN}.
Definition AlignSVG.h:402
Container for Axis and Pos.
Definition AlignSVG.h:136
Alignment(const Alignment &ac)
Copy constructor.
Definition AlignSVG.h:152
Alignment(AlignBase::Pos pos=AlignBase::Pos::UNDEFINED_POS)
Default constructor.
Definition AlignSVG.h:147
virtual ~Alignment()
Destructor.
Definition AlignSVG.h:168
"Alternative" partial alignment configuration for single object. Partial means that either OBJECT its...
Definition AlignSVG.h:256
CompleteAlignment(const TT... args)
Constructor not setting Axis.
Definition AlignSVG.h:262
Definition AlignSVG.h:229