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/util/FileInfo.h"
42// #include "drain/util/Frame.h"
43//
44#include <string>
45#include "drain/util/EnumFlags.h"
46
47namespace drain {
48
49namespace image {
50
51
53struct AlignBase {
54
55public:
56
58 enum Pos {
59 UNDEFINED_POS = 0,
60 MIN = 1, // LEFT (if HORZ) or TOP (when VERT) 0b01010101,
61 MAX = 2, // RIGHT (if HORZ) or BOTTOM (when VERT) 0b10101010,
62 MID = 3, // 0b11111111,
63 FILL = 4,
64 // ABSOLUTE?
65 };
66
67 enum Axis {
68 // Index, must contain 0 and 1 for HORZ and VERT
69 HORZ = 0, // 0b00110011,
70 VERT = 1, // b11001100,
71 UNDEFINED_AXIS = 2,
72 };
73
74 static inline
75 Axis flip(Axis axis){
76 switch (axis){
77 case HORZ:
78 return VERT;
79 case VERT:
80 return HORZ;
81 default:
82 return UNDEFINED_AXIS;
83 }
84 };
85
86 //typedef drain::EnumDict<Coord>::dict_t pos_dict_t;
87
88 static inline
90 switch (pos){
91 case MAX:
92 return MIN;
93 case MIN:
94 return MAX;
95 case MID:
96 case FILL:
97 case UNDEFINED_POS:
98 default:
99 return pos;
100 }
101 };
102
103};
104
105
106template <>
108DRAIN_ENUM_OSTREAM(AlignBase::Axis);
109
110template <>
112DRAIN_ENUM_OSTREAM(AlignBase::Pos);
113
114
116
127template <typename AX = AlignBase::Axis, AlignBase::Axis A = AlignBase::Axis::UNDEFINED_AXIS> //, typename POS = AlignBase::Pos> // , Align::Coord POS = Align::Coord::UNDEFINED_POS>
128struct Alignment {
129
130 // Align::Axis
131 AX axis; // = V; // compiler error if different type?
132
133 //AlignBase::Pos pos
134 AlignBase::Pos pos = AlignBase::Pos::UNDEFINED_POS; // or middle?
135 //POS pos = AlignBase::Pos::UNDEFINED_POS; // or middle?
136
138 inline
139 Alignment(AlignBase::Pos pos = AlignBase::Pos::UNDEFINED_POS) : axis(A), pos(pos){
140 }
141
143 inline
144 Alignment(const Alignment & ac) : axis(ac.axis), pos(ac.pos){
145 }
146
147
148 inline
149 Alignment(AlignBase::Axis axis, AlignBase::Pos pos = AlignBase::Pos::UNDEFINED_POS): axis(axis), pos(pos){
150 }
151
152 template <typename AX2, AlignBase::Axis A2>
153 inline
154 Alignment(const Alignment<AX2,A2> & align) : pos(align.pos){ // axis(ac.axis),
155 axis = align.axis; // error if const
156 }
157
159 inline virtual
161
162
163 inline
164 const AlignBase::Axis & get(const AlignBase::Axis & defaultValue) const {
165 if (axis != AlignBase::Axis::UNDEFINED_AXIS){
166 return axis;
167 }
168 else {
169 return defaultValue;
170 }
171 }
172
173 inline
174 const AlignBase::Pos & get(const AlignBase::Pos & defaultValue) const {
175 if (pos != AlignBase::Pos::UNDEFINED_POS){
176 return pos;
177 }
178 else {
179 return defaultValue;
180 }
181 }
182
183
184 virtual inline
185 void reset(){
186 axis = AlignBase::Axis::UNDEFINED_AXIS;
187 pos = AlignBase::Pos::UNDEFINED_POS;
188 }
189
190
191 template <typename AX2, AlignBase::Axis A2>
192 inline
193 bool operator==(const Alignment<AX2,A2> & align) const {
194 return (align.axis == axis) && (align.pos == pos);
195 // return compare(ad) == 0;
196 }
197
198
199};
200
201
202
203template <typename AX, AlignBase::Axis V>
204inline
205std::ostream & operator<<(std::ostream &ostr, const Alignment<AX,V> & align){
206 //return ostr << align.axis << '_' << align.pos; // enums resolved above
207 return ostr << align.axis << '_' << align.pos;
208}
209
210
211
212
213//struct Alignment2;
214
216
222struct AlignSVG { // : protected Align {
223
224
225 virtual
226 ~AlignSVG(){};
227
229
231 static
232 const HorzAlign LEFT; // ,Coord::MIN
233
235 static
237
239 static
241
243 static
245
246 static
247 const HorzAlign UNDEFINED_HORZ;
248
249 // ----------------------
250
252
254 static
256
258 static
260
262 static
264
266 static
268
269 static
270 const VertAlign UNDEFINED_VERT;
271
272
273 enum Owner {
274 OBJECT = 0, // 0b00001111,
275 ANCHOR = 1, // 0b11110000,
276 };
277
278
279 enum Topol {
280 INSIDE = 0,
281 OUTSIDE = 1,
282 UNDEFINED_TOPOL = 2,
283 };
284
285
287 /*
288 * Notice that for an alignment to be complete, this function should be called twice:
289 * setting partial alignment for both owner=OBJECT and owner=ANCHOR .
290 *
291 * \tparam OBJ - enum type \c Owner or string
292 * \tparam A - enum type \c Axis or string
293 * \tparam V - enum type \c Alignment or string
294 * \param pos - enum value \c OBJ or \c REF
295 * \param axis - enum value \c HORZ or \c VERT
296 * \param value - enum value \c MAX , \c MID , or \c MIN (or string)
297 */
298 template <typename OBJ, typename A, typename V>
299 inline // in problems, rename this function, ie. remove polymorphism
300 void setAlign(const OBJ & owner, const A & axis, const V &value){
301 modifyAlign(owner, axis, value);
302 updateAlign();
303 }
304
306
315 inline
316 void setAlign(const AlignBase::Axis & axis, const AlignBase::Pos & pos, Topol topol=Topol::INSIDE){
317 if (pos != AlignBase::FILL){
318 modifyAlign(ANCHOR, axis, pos);
319 }
320 modifyAlign(OBJECT, axis, (topol==INSIDE) ? pos : AlignBase::flip(pos));
321 updateAlign();
322 }
323
325 /*
326 * Template supports empty arg list.
327 *
328 * \tparam T - enum type \c Topol or string
329 * \tparam AX - axis enum type: Axis or const Axis
330 * \tparam A - axis enum value: HORZ, VERT or UNDEFINED_AXIS
331 * \param align - \c HorzAlign or \c VertAlign
332 */
333 template <typename ...T, typename AX, AlignBase::Axis A>
334 void setAlign(const Alignment<AX,A> & align, const T... args){
335 if (align.pos == AlignBase::FILL){
336 // Makes sense only for OBJECT, as it will be changed (and ANCHOR is never unchanged).
337 setAlign(AlignSVG::OBJECT, align.axis, align.pos);
338 }
339 else {
340 setAlign(align.axis, align.pos, args...);
341 }
342 }
343
344 // Convenience: set both horz and vert alignments (INSIDE)
345 /*
346 */
347 template <typename AX1, AlignBase::Axis A1, typename AX2, AlignBase::Axis A2>
348 void setAlign(const Alignment<AX1,A1> & align1, const Alignment<AX2,A2> & align2){
349 setAlign(align1.axis, align1.pos, AlignSVG::Topol::INSIDE);
350 setAlign(align2.axis, align2.pos, AlignSVG::Topol::INSIDE);
351 }
352
354 template <typename AX, AlignBase::Axis A>
355 void setAlign(const Alignment<AX,A> & align1, const Alignment<AX,A> & align2);
356
357
359 /*
360 * \tparam T - enum type \c Topol or string: \c INSIDE or \c OUTSIDE .
361 * \param align - Horizontal or vertical Alignment: \c LEFT|CENTER|RIGHT or \c TOP|MIDDLE|BOTTOM
362 * \param topol - \c INSIDE or \c OUTSIDE
363 */
364 template <typename T>
365 void setAlign(const std::string & align, const T & topol){
366 const Alignment<> & a = EnumDict<Alignment<> >::getValue(align, false);
367 const Topol & t = EnumDict<AlignSVG::Topol>::getValue(topol, false);
368 //const Alignment<> & a = EnumDict<Alignment<> >::getValue(align, false);
369 setAlign(a.axis, a.pos, t);
370 }
371
373
375 void setAlign(const std::string & align);
376 // Note: no mixed type, ANCHOR:LEFT
377
379 bool isAligned() const;
380
381 void resetAlign();
382
383 void swapAlign(AlignSVG & align);
384
386 /*
387 * \tparam P - enum type Owner \c REF or \c OBJ , or respective string.
388 * \tparam A - enum type axis_t \c HORZ or \c VERT , or respective string.
389 * \param pos - target object \c OBJ or referred anchor object \c REF
390 * \param axis - horizontal \c HORZ or vertical \c AXIS .
391 */
392 template <typename P, typename A>
393 AlignBase::Pos & getAlign(const P & pos, const A & axis);
394
395
397 /*
398 * \tparam P - enum type Owner \c REF or \c OBJ , or respective string.
399 * \tparam A - enum type axis_t \c HORZ or \c VERT , or respective string.
400 * \param pos - target object \c OBJ or referred anchor object \c REF
401 * \param axis - horizontal \c HORZ or vertical \c AXIS .
402 *
403 */
404 template <typename P, typename A>
405 const AlignBase::Pos & getAlign(const P & pos, const A & axis) const;
406
410 void confToStream(std::ostream & ostr) const;
411
412 inline
413 const std::string & getAlignStr() const {
414 return alignStr;
415 }
416
417 void swapAlign();
418 /*
420 template <typename ...TT>
421 bool isAlignSet(const TT... args) const {
422 bitvect_t v = combineAlign(args...);
423 return (alignment & v) == v;
424 }
425
426 */
427
428protected:
429
430 // Future extension
431 typedef int bitvect_t; // or int_t ?
432
433 // Future extension
434 mutable
435 bitvect_t alignment = 0;
436
437 std::string alignStr;
438
440 template <typename P, typename A, typename V>
441 void modifyAlign(const P & owner, const A & axis, const V &value){
442 getAlign(owner, axis) = EnumDict<AlignBase::Pos>::getValue(value, false);
443 }
444
445
446 void updateAlignStr();
447
448 virtual inline
449 void updateAlign(){
450 updateAlignStr();
451 };
452
453
454 typedef std::vector<AlignBase::Pos> align_vect_t;
455 typedef std::vector<align_vect_t > align_conf_t;
456
457 align_conf_t alignments = align_conf_t(2, align_vect_t(2, AlignBase::Pos::UNDEFINED_POS));
458
460
461
462};
463
464
465inline
466std::ostream & operator<<(std::ostream &ostr, const AlignSVG & align){
467 //return ostr << align.axis << '_' << align.pos; // enums resolved above
468 align.confToStream(ostr);
469 return ostr; // << "UNDER CONSTR..."; // RESOLVE!
470}
471
472
473// template <>
474// const drain::EnumDict<AlignSVG::Owner>::dict_t drain::EnumDict<AlignSVG::Owner>::dict;
475DRAIN_ENUM_DICT(AlignSVG::Owner);
476DRAIN_ENUM_OSTREAM(AlignSVG::Owner);
477
478//template <>
479//const drain::EnumDict<AlignSVG::Topol>::dict_t drain::EnumDict<AlignSVG::Topol>::dict;
480DRAIN_ENUM_DICT(AlignSVG::Topol);
481DRAIN_ENUM_OSTREAM(AlignSVG::Topol);
482
483template <>
484inline
485void AlignSVG::HorzAlign::reset(){
486 // axis = AlignBase::Axis::UNDEFINED_AXIS;
487 pos = AlignBase::Pos::UNDEFINED_POS;
488}
489
490template <>
491inline
492void AlignSVG::VertAlign::reset(){
493 // axis = AlignBase::Axis::UNDEFINED_AXIS;
494 pos = AlignBase::Pos::UNDEFINED_POS;
495}
496
497DRAIN_TYPENAME(AlignSVG::HorzAlign);
498
499DRAIN_TYPENAME(AlignSVG::VertAlign);
500
502template <>
504// DRAIN_ENUM_OSTREAM(AlignSVG::HorzAlign);
505
507template <>
509// DRAIN_ENUM_OSTREAM(AlignSVG::VertAlign);
510
511
513template <>
515
516
517
518
519template <typename OBJ, typename A>
520AlignBase::Pos & AlignSVG::getAlign(const OBJ & owner, const A & axis){
521 const AlignSVG::Owner p = EnumDict<AlignSVG::Owner>::getValue(owner, false); // raise error
522 const AlignBase::Axis a = EnumDict<AlignBase::Axis>::getValue(axis, false); // raise error
523 return alignments[p][a];
524}
525
526template <typename OBJ, typename A>
527const AlignBase::Pos & AlignSVG::getAlign(const OBJ & owner, const A & axis) const {
528 const AlignSVG::Owner p = EnumDict<AlignSVG::Owner>::getValue(owner, false); // raise error
529 const AlignBase::Axis a = EnumDict<AlignBase::Axis>::getValue(axis, false); // raise error
530 return alignments[p][a];
531}
532
533
534
535
536
537
539
552template <typename AX = AlignBase::Axis, AlignBase::Axis A = AlignBase::Axis::UNDEFINED_AXIS> // , Align::Coord POS = Align::Coord::UNDEFINED_POS>
553struct CompleteAlignment : public Alignment<AX,A> {
554
555 AlignSVG::Topol topol = AlignSVG::Topol::INSIDE; // or undef?
556
558 template <class ...TT>
559 CompleteAlignment(const TT... args) : Alignment<AX,A>() {
560 set(args...);
561 }
562
563 inline
565
566 virtual inline
567 bool isSet() const {
568 return (this->axis != AlignBase::Axis::UNDEFINED_AXIS) &&
569 (this->pos != AlignBase::Pos::UNDEFINED_POS) &&
570 (topol != AlignSVG::Topol::UNDEFINED_TOPOL);
571 // return Alignment<AX,A>::isSet() && (topol != AlignSVG::Topol::UNDEFINED_TOPOL);
572 }
573
574 inline
575 const AlignSVG::Topol & getOrDefault(const AlignSVG::Topol & defaultValue) const {
576 if (topol != AlignSVG::Topol::UNDEFINED_TOPOL){
577 return topol;
578 }
579 else {
580 return defaultValue;
581 }
582 }
583
584
585 // Sets all members to UNDEFINED state.
586 virtual inline
587 void reset(){
588 Alignment<AX,A>::reset();
589 topol = AlignSVG::Topol::UNDEFINED_TOPOL;
590 // this->updateAlign();
591 }
592
593
594 template <typename AX2, AlignBase::Axis A2, class ...TT>
595 void set(const Alignment<AX2,A2> & align, const TT... args){
596 this->axis = align.axis;
597 this->pos = align.pos;
598 set(args...);
599 }
600
601 template <class ...TT>
602 void set(AlignSVG::Topol topol, const TT... args){
603 this->topol = topol;
604 set(args...);
605 }
606
607 template <class ...TT>
608 void set(AlignBase::Axis axis, const TT... args){
609 this->axis = axis;
610 set(args...);
611 }
612
613 template <class ...TT>
614 void set(AlignBase::Pos coord, const TT... args){
615 this->pos = coord;
616 set(args...);
617 }
618
619 template <class ...TT>
620 void set(const std::string & key, const TT... args){
622 // ok
623 }
624 else if (EnumDict<Alignment<> >::setValue(key, *this)){ // RIGHT or?
625 // ok
626 }
627 else if (EnumDict<AlignBase::Axis>::setValue(key, this->axis)){
628 // ok
629 }
630 else if (EnumDict<AlignBase::Pos>::setValue(key, this->pos)){
631 // ok
632 }
633 else {
634 // Advice: keys
635 throw std::runtime_error(drain::StringBuilder<>("key '", key, "' not found. Appeared in: ", args...));
636 }
637
638 set(args...);
639 }
640
641 template <class ...TT>
642 void set(const char *key, const TT... args){
643 set(std::string(key), args...);
644 }
645
646
647protected:
648
649 inline
650 void set(){
651 // this->updateAlign(); // ok?
652 }
653
654};
655
656
657
658template <typename AX, AlignBase::Axis A>
659std::ostream & operator<<(std::ostream &ostr, const CompleteAlignment<AX,A> & ad){
660 return ostr << ad.topol << '_' << ad.axis << ':' << ad.pos;
661}
662
663
664
665
666
667
668
669} // image::
670
671} // drain::
672
673
674DRAIN_ENUM_OSTREAM(drain::image::AlignBase::Axis);
675DRAIN_ENUM_OSTREAM(drain::image::AlignBase::Pos);
676DRAIN_ENUM_OSTREAM(drain::image::AlignSVG::Owner);
677
678
679#endif // DRAIN_ALIGN_SVG_H_
680
Two-way mapping between strings and objects of template class T.
Definition Dictionary.h:63
Definition StringBuilder.h:58
Definition DataSelector.cpp:1277
DRAIN_TYPENAME(void)
Add a specialization for each type of those you want to support.
A container for a static dictionary of enumeration values.
Definition EnumFlags.h:69
static E getValue(const E &value, bool lenient=true)
Convenience for object.set(...) like commands.
Definition EnumFlags.h:114
static bool setValue(const std::string &key, E &value)
Assign string values to an enumeration type.
Definition EnumFlags.h:96
Low level alignment instructions.
Definition AlignSVG.h:53
Pos
Reference position at Axis (HORZ or VERT)
Definition AlignSVG.h:58
User-friendly programming interface for alignment considering two elements.
Definition AlignSVG.h:222
static const HorzAlign LEFT
Alias for {HORZ:MIN}.
Definition AlignSVG.h:232
static const VertAlign MIDDLE
Alias for {VERT:MID}.
Definition AlignSVG.h:259
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:365
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:300
void setAlign(const AlignBase::Axis &axis, const AlignBase::Pos &pos, Topol topol=Topol::INSIDE)
Set a single alignment setting. "Intermediate-level": axis and pos are given separately.
Definition AlignSVG.h:316
const AlignBase::Pos & getAlign(const P &pos, const A &axis) const
Return alignment setting of an object along horizontal or vertical axis .
void confToStream(std::ostream &ostr) const
Definition AlignSVG.cpp:173
bool isAligned() const
Returns true, if any setting is set...
Definition AlignSVG.cpp:264
static const HorzAlign RIGHT
Alias for {HORZ:MAX}.
Definition AlignSVG.h:240
static const HorzAlign HORZ_FILL
Alias for {HORZ:FILL}.
Definition AlignSVG.h:244
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:441
static const VertAlign VERT_FILL
Alias for {VERT:FILL}.
Definition AlignSVG.h:267
static const VertAlign BOTTOM
Alias for {VERT:MAX}.
Definition AlignSVG.h:263
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:334
static const HorzAlign CENTER
Alias for {HORZ:MID}.
Definition AlignSVG.h:236
static const VertAlign TOP
Alias for {VERT:MIN}.
Definition AlignSVG.h:255
AlignBase::Pos & getAlign(const P &pos, const A &axis)
Return alignment setting of an object along horizontal or vertical axis .
Container for Axis and Pos.
Definition AlignSVG.h:128
Alignment(const Alignment &ac)
Copy constructor.
Definition AlignSVG.h:144
Alignment(AlignBase::Pos pos=AlignBase::Pos::UNDEFINED_POS)
Default constructor.
Definition AlignSVG.h:139
virtual ~Alignment()
Destructor.
Definition AlignSVG.h:160
"Alternative" partial alignment configuration for single object. Partial means that either OBJECT its...
Definition AlignSVG.h:553
CompleteAlignment(const TT... args)
Constructor not setting Axis.
Definition AlignSVG.h:559