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