1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 Jochen Becher
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "defaultstyleengine.h"
27
28 #include "defaultstyle.h"
29 #include "objectvisuals.h"
30 #include "styledobject.h"
31 #include "styledrelation.h"
32
33 #include "qmt/diagram/dclass.h"
34 #include "qmt/diagram/dpackage.h"
35 #include "qmt/diagram/dcomponent.h"
36 #include "qmt/diagram/ditem.h"
37 #include "qmt/diagram/dannotation.h"
38 #include "qmt/infrastructure/qmtassert.h"
39
40 #include <utils/algorithm.h>
41
42 #include <QSet>
43
44 namespace {
45
46 class DepthProperties
47 {
48 public:
49 DepthProperties() = default;
DepthProperties(qmt::DefaultStyleEngine::ElementType elementType,qmt::DObject::VisualPrimaryRole visualPrimaryRole,qmt::DObject::VisualSecondaryRole visualSecondaryRole)50 DepthProperties(qmt::DefaultStyleEngine::ElementType elementType,
51 qmt::DObject::VisualPrimaryRole visualPrimaryRole,
52 qmt::DObject::VisualSecondaryRole visualSecondaryRole)
53 : m_elementType(elementType),
54 m_visualPrimaryRole(visualPrimaryRole),
55 m_visualSecondaryRole(visualSecondaryRole)
56 {
57 }
58
59 qmt::DefaultStyleEngine::ElementType m_elementType = qmt::DefaultStyleEngine::TypeOther;
60 qmt::DObject::VisualPrimaryRole m_visualPrimaryRole = qmt::DObject::PrimaryRoleNormal;
61 qmt::DObject::VisualSecondaryRole m_visualSecondaryRole = qmt::DObject::SecondaryRoleNone;
62 };
63
64 } // namespace
65
66 namespace qmt {
67
68 // TODO use tuple instead of these 4 explicit key classes
69
70 class ObjectStyleKey
71 {
72 public:
73 ObjectStyleKey() = default;
74
ObjectStyleKey(StyleEngine::ElementType elementType,const ObjectVisuals & objectVisuals)75 ObjectStyleKey(StyleEngine::ElementType elementType, const ObjectVisuals &objectVisuals)
76 : m_elementType(elementType),
77 m_objectVisuals(objectVisuals)
78 {
79 }
80
81 StyleEngine::ElementType m_elementType = StyleEngine::TypeOther;
82 ObjectVisuals m_objectVisuals;
83 };
84
qHash(const ObjectStyleKey & styleKey)85 uint qHash(const ObjectStyleKey &styleKey)
86 {
87 return ::qHash(styleKey.m_elementType) ^ qHash(styleKey.m_objectVisuals);
88 }
89
operator ==(const ObjectStyleKey & lhs,const ObjectStyleKey & rhs)90 bool operator==(const ObjectStyleKey &lhs, const ObjectStyleKey &rhs)
91 {
92 return lhs.m_elementType == rhs.m_elementType && lhs.m_objectVisuals == rhs.m_objectVisuals;
93 }
94
95 class RelationStyleKey
96 {
97 public:
RelationStyleKey(StyleEngine::ElementType elementType=StyleEngine::TypeOther,DObject::VisualPrimaryRole visualPrimaryRole=DObject::PrimaryRoleNormal)98 RelationStyleKey(StyleEngine::ElementType elementType = StyleEngine::TypeOther,
99 DObject::VisualPrimaryRole visualPrimaryRole = DObject::PrimaryRoleNormal)
100 : m_elementType(elementType),
101 m_visualPrimaryRole(visualPrimaryRole)
102 {
103 }
104
105 StyleEngine::ElementType m_elementType = StyleEngine::TypeOther;
106 DObject::VisualPrimaryRole m_visualPrimaryRole = DObject::PrimaryRoleNormal;
107 };
108
qHash(const RelationStyleKey & styleKey)109 uint qHash(const RelationStyleKey &styleKey)
110 {
111 return ::qHash(styleKey.m_elementType) ^ ::qHash(styleKey.m_visualPrimaryRole);
112 }
113
operator ==(const RelationStyleKey & lhs,const RelationStyleKey & rhs)114 bool operator==(const RelationStyleKey &lhs, const RelationStyleKey &rhs)
115 {
116 return lhs.m_elementType == rhs.m_elementType && lhs.m_visualPrimaryRole == rhs.m_visualPrimaryRole;
117 }
118
119 class AnnotationStyleKey
120 {
121 public:
AnnotationStyleKey(DAnnotation::VisualRole visualRole=DAnnotation::RoleNormal)122 AnnotationStyleKey(DAnnotation::VisualRole visualRole = DAnnotation::RoleNormal)
123 : m_visualRole(visualRole)
124 {
125 }
126
127 DAnnotation::VisualRole m_visualRole = DAnnotation::RoleNormal;
128 };
129
qHash(const AnnotationStyleKey & styleKey)130 uint qHash(const AnnotationStyleKey &styleKey)
131 {
132 return ::qHash(styleKey.m_visualRole);
133 }
134
operator ==(const AnnotationStyleKey & lhs,const AnnotationStyleKey & rhs)135 bool operator==(const AnnotationStyleKey &lhs, const AnnotationStyleKey &rhs)
136 {
137 return lhs.m_visualRole == rhs.m_visualRole;
138 }
139
140 // TODO remove class if no attributes needed even with future extensions
141 class BoundaryStyleKey
142 {
143 };
144
qHash(const BoundaryStyleKey & styleKey)145 uint qHash(const BoundaryStyleKey &styleKey)
146 {
147 Q_UNUSED(styleKey)
148
149 return 1;
150 }
151
operator ==(const BoundaryStyleKey & lhs,const BoundaryStyleKey & rhs)152 bool operator==(const BoundaryStyleKey &lhs, const BoundaryStyleKey &rhs)
153 {
154 Q_UNUSED(lhs)
155 Q_UNUSED(rhs)
156
157 return true;
158 }
159
160 // TODO remove class if no attributes needed even with future extensions
161 class SwimlaneStyleKey
162 {
163 };
164
qHash(const SwimlaneStyleKey & styleKey)165 uint qHash(const SwimlaneStyleKey &styleKey)
166 {
167 Q_UNUSED(styleKey)
168
169 return 1;
170 }
171
operator ==(const SwimlaneStyleKey & lhs,const SwimlaneStyleKey & rhs)172 bool operator==(const SwimlaneStyleKey &lhs, const SwimlaneStyleKey &rhs)
173 {
174 Q_UNUSED(lhs)
175 Q_UNUSED(rhs)
176
177 return true;
178 }
179
DefaultStyleEngine()180 DefaultStyleEngine::DefaultStyleEngine()
181 {
182 }
183
~DefaultStyleEngine()184 DefaultStyleEngine::~DefaultStyleEngine()
185 {
186 qDeleteAll(m_objectStyleMap);
187 qDeleteAll(m_relationStyleMap);
188 qDeleteAll(m_annotationStyleMap);
189 qDeleteAll(m_boundaryStyleMap);
190 }
191
applyStyle(const Style * baseStyle,StyleEngine::ElementType elementType,const StyleEngine::Parameters * parameters)192 const Style *DefaultStyleEngine::applyStyle(const Style *baseStyle, StyleEngine::ElementType elementType,
193 const StyleEngine::Parameters *parameters)
194 {
195 switch (elementType) {
196 case TypeAnnotation:
197 return applyAnnotationStyle(baseStyle, DAnnotation::RoleNormal, parameters);
198 case TypeBoundary:
199 return applyBoundaryStyle(baseStyle, parameters);
200 case TypeRelation:
201 break;
202 case TypeClass:
203 case TypeComponent:
204 case TypeItem:
205 case TypePackage:
206 return applyObjectStyle(
207 baseStyle, elementType,
208 ObjectVisuals(DObject::PrimaryRoleNormal, DObject::SecondaryRoleNone, false, QColor(), 0),
209 parameters);
210 case TypeOther:
211 break;
212 case TypeSwimlane:
213 return applySwimlaneStyle(baseStyle, parameters);
214 }
215 return baseStyle;
216 }
217
applyObjectStyle(const Style * baseStyle,StyleEngine::ElementType elementType,const ObjectVisuals & objectVisuals,const StyleEngine::Parameters * parameters)218 const Style *DefaultStyleEngine::applyObjectStyle(const Style *baseStyle, StyleEngine::ElementType elementType,
219 const ObjectVisuals &objectVisuals,
220 const StyleEngine::Parameters *parameters)
221 {
222 ObjectStyleKey key(elementType, objectVisuals);
223 const Style *derivedStyle = m_objectStyleMap.value(key);
224 if (!derivedStyle) {
225 int lineWidth = 1;
226
227 QColor fillColor = DefaultStyleEngine::fillColor(elementType, objectVisuals);
228 QColor lineColor = DefaultStyleEngine::lineColor(elementType, objectVisuals);
229 QColor textColor = DefaultStyleEngine::textColor(elementType, objectVisuals);
230
231 QFont normalFont = baseStyle->normalFont();
232 QFont headerFont = baseStyle->normalFont();
233 if (objectVisuals.isEmphasized()) {
234 lineWidth = 2;
235 headerFont.setBold(true);
236 }
237
238 auto style = new Style(baseStyle->type());
239 QPen linePen = baseStyle->linePen();
240 linePen.setColor(lineColor);
241 linePen.setWidth(lineWidth);
242 style->setLinePen(linePen);
243 style->setInnerLinePen(linePen);
244 style->setOuterLinePen(linePen);
245 style->setExtraLinePen(linePen);
246 style->setTextBrush(QBrush(textColor));
247 if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleOutline) {
248 style->setFillBrush(QBrush(Qt::white));
249 } else if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleFlat) {
250 style->setFillBrush(QBrush(fillColor));
251 } else {
252 if (!parameters->suppressGradients()) {
253 QLinearGradient fillGradient(0.0, 0.0, 0.0, 1.0);
254 fillGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
255 fillGradient.setColorAt(0.0, fillColor.lighter(110));
256 fillGradient.setColorAt(1.0, fillColor.darker(110));
257 style->setFillBrush(QBrush(fillGradient));
258 } else {
259 style->setFillBrush(QBrush(fillColor));
260 }
261 }
262 if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleOutline)
263 style->setExtraFillBrush(QBrush(Qt::white));
264 else if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleFlat)
265 style->setExtraFillBrush(QBrush(fillColor));
266 else
267 style->setExtraFillBrush(QBrush(fillColor.darker(120)));
268 style->setNormalFont(normalFont);
269 style->setSmallFont(baseStyle->smallFont());
270 style->setHeaderFont(headerFont);
271 m_objectStyleMap.insert(key, style);
272 derivedStyle = style;
273 }
274
275 return derivedStyle;
276 }
277
applyObjectStyle(const Style * baseStyle,const StyledObject & styledObject,const Parameters * parameters)278 const Style *DefaultStyleEngine::applyObjectStyle(const Style *baseStyle, const StyledObject &styledObject,
279 const Parameters *parameters)
280 {
281 ElementType elementType = objectType(styledObject.object());
282
283 // find colliding elements which best match visual appearance of styled object
284 DObject::VisualPrimaryRole styledVisualPrimaryRole = styledObject.objectVisuals().visualPrimaryRole();
285 DObject::VisualSecondaryRole styledVisualSecondaryRole = styledObject.objectVisuals().visualSecondaryRole();
286 QHash<int, DepthProperties> depths;
287 foreach (const DObject *collidingObject, styledObject.collidingObjects()) {
288 int collidingDepth = collidingObject->depth();
289 if (collidingDepth < styledObject.object()->depth()) {
290 ElementType collidingElementType = objectType(collidingObject);
291 DObject::VisualPrimaryRole collidingVisualPrimaryRole = collidingObject->visualPrimaryRole();
292 DObject::VisualSecondaryRole collidingVisualSecondaryRole = collidingObject->visualSecondaryRole();
293 if (!depths.contains(collidingDepth)) {
294 depths.insert(collidingDepth, DepthProperties(collidingElementType, collidingVisualPrimaryRole,
295 collidingVisualSecondaryRole));
296 } else {
297 bool updateProperties = false;
298 DepthProperties properties = depths.value(collidingDepth);
299 if (properties.m_elementType != elementType && collidingElementType == elementType) {
300 properties.m_elementType = collidingElementType;
301 properties.m_visualPrimaryRole = collidingVisualPrimaryRole;
302 properties.m_visualSecondaryRole = collidingVisualSecondaryRole;
303 updateProperties = true;
304 } else if (properties.m_elementType == elementType && collidingElementType == elementType) {
305 if ((properties.m_visualPrimaryRole != styledVisualPrimaryRole
306 || properties.m_visualSecondaryRole != styledVisualSecondaryRole)
307 && collidingVisualPrimaryRole == styledVisualPrimaryRole
308 && collidingVisualSecondaryRole == styledVisualSecondaryRole) {
309 properties.m_visualPrimaryRole = collidingVisualPrimaryRole;
310 properties.m_visualSecondaryRole = collidingVisualSecondaryRole;
311 updateProperties = true;
312 }
313 }
314 if (updateProperties)
315 depths.insert(collidingDepth, properties);
316 }
317 }
318 }
319 int depth = 0;
320 if (!depths.isEmpty()) {
321 QList<int> keys = depths.keys();
322 Utils::sort(keys);
323 foreach (int d, keys) {
324 DepthProperties properties = depths.value(d);
325 if (properties.m_elementType == elementType
326 && areStackingRoles(properties.m_visualPrimaryRole, properties.m_visualSecondaryRole,
327 styledVisualPrimaryRole, styledVisualSecondaryRole)) {
328 ++depth;
329 } else {
330 depth = 0;
331 }
332 }
333 }
334
335 return applyObjectStyle(baseStyle, elementType,
336 ObjectVisuals(styledVisualPrimaryRole,
337 styledVisualSecondaryRole,
338 styledObject.objectVisuals().isEmphasized(),
339 styledObject.objectVisuals().baseColor(),
340 depth),
341 parameters);
342 }
343
applyRelationStyle(const Style * baseStyle,const StyledRelation & styledRelation,const Parameters * parameters)344 const Style *DefaultStyleEngine::applyRelationStyle(const Style *baseStyle, const StyledRelation &styledRelation,
345 const Parameters *parameters)
346 {
347 Q_UNUSED(parameters)
348
349 ElementType elementType = objectType(styledRelation.endA());
350 RelationStyleKey key(elementType, styledRelation.endA() ? styledRelation.endA()->visualPrimaryRole() : DObject::PrimaryRoleNormal);
351 const Style *derivedStyle = m_relationStyleMap.value(key);
352 if (!derivedStyle) {
353 auto style = new Style(baseStyle->type());
354
355 const DObject *object = styledRelation.endA();
356 ObjectVisuals objectVisuals(object ? object->visualPrimaryRole() : DObject::PrimaryRoleNormal,
357 object ? object->visualSecondaryRole() : DObject::SecondaryRoleNone,
358 object ? object->isVisualEmphasized() : false,
359 Qt::black, // TODO STyledRelation should get an EndAObjectVisuals
360 object ? object->depth() : 0);
361 QColor lineColor = DefaultStyleEngine::lineColor(objectType(object), objectVisuals);
362 QColor fillColor = lineColor;
363
364 QPen linePen = baseStyle->linePen();
365 linePen.setWidth(1);
366 linePen.setColor(lineColor);
367 style->setLinePen(linePen);
368 QBrush textBrush = baseStyle->textBrush();
369 textBrush.setColor(QColor("black"));
370 style->setTextBrush(textBrush);
371 QBrush brush = baseStyle->fillBrush();
372 brush.setColor(fillColor);
373 brush.setStyle(Qt::SolidPattern);
374 style->setFillBrush(brush);
375 style->setNormalFont(baseStyle->normalFont());
376 style->setSmallFont(baseStyle->smallFont());
377 style->setHeaderFont(baseStyle->headerFont());
378 m_relationStyleMap.insert(key, style);
379 derivedStyle = style;
380 }
381 return derivedStyle;
382 }
383
applyAnnotationStyle(const Style * baseStyle,const DAnnotation * annotation,const Parameters * parameters)384 const Style *DefaultStyleEngine::applyAnnotationStyle(const Style *baseStyle, const DAnnotation *annotation,
385 const Parameters *parameters)
386 {
387 DAnnotation::VisualRole visualRole = annotation ? annotation->visualRole() : DAnnotation::RoleNormal;
388 return applyAnnotationStyle(baseStyle, visualRole, parameters);
389 }
390
applyBoundaryStyle(const Style * baseStyle,const DBoundary * boundary,const Parameters * parameters)391 const Style *DefaultStyleEngine::applyBoundaryStyle(const Style *baseStyle, const DBoundary *boundary,
392 const Parameters *parameters)
393 {
394 Q_UNUSED(boundary)
395
396 return applyBoundaryStyle(baseStyle, parameters);
397 }
398
applySwimlaneStyle(const Style * baseStyle,const DSwimlane * swimlane,const StyleEngine::Parameters * parameters)399 const Style *DefaultStyleEngine::applySwimlaneStyle(const Style *baseStyle, const DSwimlane *swimlane, const StyleEngine::Parameters *parameters)
400 {
401 Q_UNUSED(swimlane)
402
403 return applySwimlaneStyle(baseStyle, parameters);
404 }
405
applyAnnotationStyle(const Style * baseStyle,DAnnotation::VisualRole visualRole,const StyleEngine::Parameters * parameters)406 const Style *DefaultStyleEngine::applyAnnotationStyle(const Style *baseStyle, DAnnotation::VisualRole visualRole,
407 const StyleEngine::Parameters *parameters)
408 {
409 Q_UNUSED(parameters)
410
411 AnnotationStyleKey key(visualRole);
412 const Style *derivedStyle = m_annotationStyleMap.value(key);
413 if (!derivedStyle) {
414 auto style = new Style(baseStyle->type());
415 QFont normalFont;
416 QBrush textBrush = baseStyle->textBrush();
417 switch (visualRole) {
418 case DAnnotation::RoleNormal:
419 normalFont = baseStyle->normalFont();
420 break;
421 case DAnnotation::RoleTitle:
422 normalFont = baseStyle->headerFont();
423 break;
424 case DAnnotation::RoleSubtitle:
425 normalFont = baseStyle->normalFont();
426 normalFont.setItalic(true);
427 break;
428 case DAnnotation::RoleEmphasized:
429 normalFont = baseStyle->normalFont();
430 normalFont.setBold(true);
431 break;
432 case DAnnotation::RoleSoften:
433 normalFont = baseStyle->normalFont();
434 textBrush.setColor(Qt::gray);
435 break;
436 case DAnnotation::RoleFootnote:
437 normalFont = baseStyle->smallFont();
438 break;
439 }
440 style->setNormalFont(normalFont);
441 style->setTextBrush(textBrush);
442 m_annotationStyleMap.insert(key, style);
443 derivedStyle = style;
444 }
445 return derivedStyle;
446 }
447
applyBoundaryStyle(const Style * baseStyle,const StyleEngine::Parameters * parameters)448 const Style *DefaultStyleEngine::applyBoundaryStyle(const Style *baseStyle, const StyleEngine::Parameters *parameters)
449 {
450 Q_UNUSED(parameters)
451
452 BoundaryStyleKey key;
453 const Style *derivedStyle = m_boundaryStyleMap.value(key);
454 if (!derivedStyle) {
455 auto style = new Style(baseStyle->type());
456 style->setNormalFont(baseStyle->normalFont());
457 style->setTextBrush(baseStyle->textBrush());
458 m_boundaryStyleMap.insert(key, style);
459 derivedStyle = style;
460 }
461 return derivedStyle;
462 }
463
applySwimlaneStyle(const Style * baseStyle,const StyleEngine::Parameters * parameters)464 const Style *DefaultStyleEngine::applySwimlaneStyle(const Style *baseStyle, const StyleEngine::Parameters *parameters)
465 {
466 Q_UNUSED(parameters)
467
468 SwimlaneStyleKey key;
469 const Style *derivedStyle = m_swimlaneStyleMap.value(key);
470 if (!derivedStyle) {
471 auto style = new Style(baseStyle->type());
472 style->setNormalFont(baseStyle->normalFont());
473 style->setTextBrush(baseStyle->textBrush());
474 m_swimlaneStyleMap.insert(key, style);
475 derivedStyle = style;
476 }
477 return derivedStyle;
478 }
479
objectType(const DObject * object)480 DefaultStyleEngine::ElementType DefaultStyleEngine::objectType(const DObject *object)
481 {
482 ElementType elementType;
483 if (dynamic_cast<const DPackage *>(object))
484 elementType = TypePackage;
485 else if (dynamic_cast<const DComponent *>(object))
486 elementType = TypeComponent;
487 else if (dynamic_cast<const DClass *>(object))
488 elementType = TypeClass;
489 else if (dynamic_cast<const DItem *>(object))
490 elementType = TypeItem;
491 else
492 elementType = TypeOther;
493 return elementType;
494 }
495
areStackingRoles(DObject::VisualPrimaryRole rhsPrimaryRole,DObject::VisualSecondaryRole rhsSecondaryRole,DObject::VisualPrimaryRole lhsPrimaryRole,DObject::VisualSecondaryRole lhsSecondaryRols)496 bool DefaultStyleEngine::areStackingRoles(DObject::VisualPrimaryRole rhsPrimaryRole,
497 DObject::VisualSecondaryRole rhsSecondaryRole,
498 DObject::VisualPrimaryRole lhsPrimaryRole,
499 DObject::VisualSecondaryRole lhsSecondaryRols)
500 {
501 switch (rhsSecondaryRole) {
502 case DObject::SecondaryRoleNone:
503 case DObject::SecondaryRoleLighter:
504 case DObject::SecondaryRoleDarker:
505 case DObject::SecondaryRoleFlat:
506 switch (lhsSecondaryRols) {
507 case DObject::SecondaryRoleNone:
508 case DObject::SecondaryRoleLighter:
509 case DObject::SecondaryRoleDarker:
510 case DObject::SecondaryRoleFlat:
511 return lhsPrimaryRole == rhsPrimaryRole;
512 case DObject::SecondaryRoleSoften:
513 case DObject::SecondaryRoleOutline:
514 return false;
515 }
516 break;
517 case DObject::SecondaryRoleSoften:
518 case DObject::SecondaryRoleOutline:
519 return false;
520 }
521 return true;
522 }
523
baseColor(ElementType elementType,ObjectVisuals objectVisuals)524 QColor DefaultStyleEngine::baseColor(ElementType elementType, ObjectVisuals objectVisuals)
525 {
526 if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleOutline)
527 return QColor(0xFF, 0xFF, 0xFF);
528
529 QColor baseColor;
530
531 if (objectVisuals.visualPrimaryRole() == DObject::PrimaryRoleNormal) {
532 if (objectVisuals.baseColor().isValid()) {
533 baseColor = objectVisuals.baseColor();
534 } else {
535 switch (elementType) {
536 case TypePackage:
537 baseColor = QColor(0x7C, 0x98, 0xAD);
538 break;
539 case TypeComponent:
540 baseColor = QColor(0xA0, 0xA8, 0x91);
541 break;
542 case TypeClass:
543 baseColor = QColor(0xE5, 0xA8, 0x58);
544 break;
545 case TypeItem:
546 baseColor = QColor(0xB9, 0x95, 0xC6);
547 break;
548 case TypeRelation:
549 case TypeAnnotation:
550 case TypeBoundary:
551 case TypeSwimlane:
552 case TypeOther:
553 baseColor = QColor(0xBF, 0x7D, 0x65);
554 break;
555 }
556 }
557 } else {
558 static QColor customColors[] = {
559 QColor(0xEE, 0x8E, 0x99).darker(110), // ROLE_CUSTOM1,
560 QColor(0x80, 0xAF, 0x47).lighter(130), // ROLE_CUSTOM2,
561 QColor(0xFF, 0xA1, 0x5B).lighter(100), // ROLE_CUSTOM3,
562 QColor(0x55, 0xC4, 0xCF).lighter(120), // ROLE_CUSTOM4,
563 QColor(0xFF, 0xE1, 0x4B) // ROLE_CUSTOM5,
564 };
565
566 int index = static_cast<int>(objectVisuals.visualPrimaryRole()) - static_cast<int>(DObject::PrimaryRoleCustom1);
567 QMT_ASSERT(index >= 0 && index <= 4, return baseColor);
568 baseColor = customColors[index];
569 }
570
571 switch (objectVisuals.visualSecondaryRole()) {
572 case DObject::SecondaryRoleNone:
573 break;
574 case DObject::SecondaryRoleLighter:
575 baseColor = baseColor.lighter(110);
576 break;
577 case DObject::SecondaryRoleDarker:
578 baseColor = baseColor.darker(120);
579 break;
580 case DObject::SecondaryRoleSoften:
581 baseColor = baseColor.lighter(300);
582 break;
583 case DObject::SecondaryRoleOutline:
584 QMT_CHECK(false);
585 break;
586 case DObject::SecondaryRoleFlat:
587 break;
588 }
589
590 return baseColor;
591 }
592
lineColor(ElementType elementType,const ObjectVisuals & objectVisuals)593 QColor DefaultStyleEngine::lineColor(ElementType elementType, const ObjectVisuals &objectVisuals)
594 {
595 QColor lineColor;
596 if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleOutline)
597 lineColor = Qt::black;
598 else if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleSoften)
599 lineColor = Qt::gray;
600 else
601 lineColor = baseColor(elementType, objectVisuals).darker(200).lighter(150).darker(100 + objectVisuals.depth() * 10);
602 return lineColor;
603 }
604
fillColor(ElementType elementType,const ObjectVisuals & objectVisuals)605 QColor DefaultStyleEngine::fillColor(ElementType elementType, const ObjectVisuals &objectVisuals)
606 {
607 QColor fillColor;
608 if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleOutline)
609 fillColor = Qt::white;
610 else
611 fillColor = baseColor(elementType, objectVisuals).lighter(150).darker(100 + objectVisuals.depth() * 10);
612 return fillColor;
613 }
614
textColor(const DObject * object,int depth)615 QColor DefaultStyleEngine::textColor(const DObject *object, int depth)
616 {
617 Q_UNUSED(depth)
618
619 QColor textColor;
620 DObject::VisualPrimaryRole visualRole = object ? object->visualPrimaryRole() : DObject::PrimaryRoleNormal;
621 if (visualRole == DObject::DeprecatedPrimaryRoleSoften)
622 textColor = Qt::gray;
623 else
624 textColor = Qt::black;
625 return textColor;
626 }
627
textColor(ElementType elementType,const ObjectVisuals & objectVisuals)628 QColor DefaultStyleEngine::textColor(ElementType elementType, const ObjectVisuals &objectVisuals)
629 {
630 Q_UNUSED(elementType)
631
632 QColor textColor;
633 if (objectVisuals.visualSecondaryRole() == DObject::SecondaryRoleSoften)
634 textColor = Qt::gray;
635 else
636 textColor = Qt::black;
637 return textColor;
638 }
639
640 } // namespace qmt
641