File indexing completed on 2024-05-12 04:35:05
0001 /* This file is part of the TikZKit project. 0002 * 0003 * Copyright (C) 2013-2018 Dominik Haumann <dhaumann@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU Library General Public License as published 0007 * by the Free Software Foundation, either version 2 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, see 0017 * <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "Style.h" 0021 0022 #include "Document.h" 0023 #include "Visitor.h" 0024 0025 #include <QSet> 0026 0027 namespace tikz { 0028 namespace core { 0029 0030 // NOTE: these strings have to match the Q_PROPERTY strings, otherise 0031 // serialization will not work correctly. 0032 static constexpr char s_penStyle[] = "penStyle"; 0033 static constexpr char s_lineWidth[] = "lineWidth"; 0034 static constexpr char s_doubleLine[] = "doubleLine"; 0035 static constexpr char s_innerLineWidth[] = "innerLineWidth"; 0036 static constexpr char s_penOpacity[] = "penOpacity"; 0037 static constexpr char s_fillOpacity[] = "fillOpacity"; 0038 static constexpr char s_penColor[] = "penColor"; 0039 static constexpr char s_innerLineColor[] = "innerLineColor"; 0040 static constexpr char s_fillColor[] = "fillColor"; 0041 static constexpr char s_rotation[] = "rotation"; 0042 0043 // Path properties 0044 static constexpr char s_radiusX[] = "radiusX"; 0045 static constexpr char s_radiusY[] = "radiusY"; 0046 static constexpr char s_bendAngle[] = "bendAngle"; 0047 static constexpr char s_looseness[] = "looseness"; 0048 static constexpr char s_outAngle[] = "outAngle"; 0049 static constexpr char s_inAngle[] = "inAngle"; 0050 static constexpr char s_arrowTail[] = "arrowTail"; 0051 static constexpr char s_arrowHead[] = "arrowHead"; 0052 static constexpr char s_shortenStart[] = "shortenStart"; 0053 static constexpr char s_shortenEnd[] = "shortenEnd"; 0054 0055 // Node properties 0056 static constexpr char s_align[] = "textAlign"; 0057 static constexpr char s_shape[] = "shape"; 0058 static constexpr char s_innerSep[] = "innerSep"; 0059 static constexpr char s_outerSep[] = "outerSep"; 0060 static constexpr char s_minimumHeight[] = "minimumHeight"; 0061 static constexpr char s_minimumWidth[] = "minimumWidth"; 0062 0063 /** 0064 * Private data and helper functions of class Style. 0065 */ 0066 class StylePrivate 0067 { 0068 public: 0069 // parent / child hierarchy 0070 Uid parentStyle; 0071 QVector<Uid> children; 0072 0073 // config reference counter 0074 int refCounter = 0; 0075 0076 // list of set properties 0077 QSet<QString> properties; 0078 0079 // line style 0080 PenStyle penStyle = tikz::PenStyle::SolidLine; 0081 0082 // line width 0083 tikz::Value lineWidth = tikz::Value::semiThick(); 0084 0085 // double lines 0086 bool doubleLine = false; 0087 tikz::Value innerLineWidth = tikz::Value::semiThick(); 0088 0089 // colors 0090 QColor penColor = Qt::black; 0091 QColor innerLineColor = Qt::white; 0092 QColor fillColor = Qt::transparent; 0093 0094 qreal penOpacity = 1.0; 0095 qreal fillOpacity = 1.0; 0096 0097 qreal rotation = 0.0; 0098 0099 // 0100 // Path members 0101 // 0102 public: 0103 tikz::Value radiusX = 0.0_cm; 0104 tikz::Value radiusY = 0.0_cm; 0105 0106 qreal bendAngle = 0.0; // in degree 0107 qreal looseness = 1.0; 0108 qreal outAngle = 45.0; // in degree 0109 qreal inAngle = 135.0; // in degree 0110 0111 Arrow arrowTail = tikz::Arrow::NoArrow; 0112 Arrow arrowHead = tikz::Arrow::NoArrow; 0113 0114 tikz::Value shortenStart; 0115 tikz::Value shortenEnd; 0116 0117 // 0118 // Node members 0119 // 0120 public: 0121 // Node styles 0122 TextAlignment textAlign = tikz::TextAlignment::NoAlign; 0123 Shape shape = tikz::Shape::ShapeRectangle; 0124 tikz::Value innerSep = 3.0_pt; //FIXME: 0.3333em 0125 tikz::Value outerSep = 0.5_pt; // 0.5 \pgflinewidth 0126 tikz::Value minimumHeight = 0.0_cm; 0127 tikz::Value minimumWidth = 0.0_cm; 0128 }; 0129 0130 Style::Style() 0131 : Entity() 0132 , d(new StylePrivate()) 0133 { 0134 } 0135 0136 Style::Style(const Uid & uid) 0137 : Entity(uid) 0138 , d(new StylePrivate()) 0139 { 0140 } 0141 0142 Style::~Style() 0143 { 0144 // unregister all child styles 0145 for (const Uid & styleUid : qAsConst(d->children)) { 0146 styleUid.entity<Style>()->setParentStyle(d->parentStyle); 0147 } 0148 Q_ASSERT(d->children.size() == 0); 0149 0150 // avoid unnecessary propagation of the changed() signal 0151 disconnect(this, SIGNAL(changed()), nullptr, nullptr); 0152 0153 // now: remove from parent's child list, if needed 0154 setParentStyle(Uid()); 0155 } 0156 0157 tikz::EntityType Style::entityType() const 0158 { 0159 return EntityType::Style; 0160 } 0161 0162 bool Style::accept(Visitor & visitor) 0163 { 0164 visitor.visit(this); 0165 return true; 0166 } 0167 0168 void Style::setStyle(const Style * other) 0169 { 0170 if (this == other) { 0171 return; 0172 } 0173 0174 // start configuration 0175 ConfigTransaction transaction(this); 0176 0177 // backup properties not to copy 0178 Uid parent = d->parentStyle; 0179 0180 // perform copy of properties 0181 *d = *other->d; 0182 0183 // restore persistent properties 0184 d->parentStyle = parent; 0185 } 0186 0187 void Style::loadData(const QJsonObject & json) 0188 { 0189 ConfigTransaction transaction(this); 0190 0191 if (json.contains("parentStyle")) { 0192 d->parentStyle = Uid(json["parentStyle"].toString(), document()); 0193 } 0194 0195 if (json.contains("penColor")) { 0196 setPenColor(json["penColor"].toString()); 0197 } 0198 0199 if (json.contains("fillColor")) { 0200 setFillColor(json["fillColor"].toString()); 0201 } 0202 0203 if (json.contains("penOpacity")) { 0204 setPenOpacity(json["penOpacity"].toDouble()); 0205 } 0206 0207 if (json.contains("fillOpacity")) { 0208 setFillOpacity(json["fillOpacity"].toDouble()); 0209 } 0210 0211 if (json.contains("penStyle")) { 0212 setPenStyle(toEnum<PenStyle>(json["penStyle"].toString())); 0213 } 0214 0215 if (json.contains("lineWidth")) { 0216 setLineWidth(Value::fromString(json["lineWidth"].toString())); 0217 } 0218 // FIXME line type, inner line type? 0219 0220 if (json.contains("doubleLine")) { 0221 setDoubleLine(json["doubleLine"].toBool()); 0222 } 0223 0224 if (json.contains("innerLineWidth")) { 0225 setInnerLineWidth(Value::fromString(json["innerLineWidth"].toString())); 0226 } 0227 0228 if (json.contains("innerLineColor")) { 0229 setInnerLineColor(json["innerLineColor"].toString()); 0230 } 0231 0232 if (json.contains("rotation")) { 0233 setRotation(json["rotation"].toDouble()); 0234 } 0235 0236 if (json.contains("radiusX")) { 0237 setRadiusX(tikz::Value::fromString(json["radiusX"].toString())); 0238 } 0239 0240 if (json.contains("radiusY")) { 0241 setRadiusY(tikz::Value::fromString(json["radiusY"].toString())); 0242 } 0243 0244 if (json.contains("bendAngle")) { 0245 setBendAngle(json["bendAngle"].toDouble()); 0246 } 0247 0248 if (json.contains("looseness")) { 0249 setLooseness(json["looseness"].toDouble()); 0250 } 0251 0252 if (json.contains("outAngle")) { 0253 setOutAngle(json["outAngle"].toDouble()); 0254 } 0255 0256 if (json.contains("inAngle")) { 0257 setInAngle(json["inAngle"].toDouble()); 0258 } 0259 0260 if (json.contains("arrowTail")) { 0261 setArrowTail(toEnum<Arrow>(json["arrowTail"].toString())); 0262 } 0263 0264 if (json.contains("arrowHead")) { 0265 setArrowHead(toEnum<Arrow>(json["arrowHead"].toString())); 0266 } 0267 0268 if (json.contains("shortenStart")) { 0269 setShortenStart(tikz::Value::fromString(json["shortenStart"].toString())); 0270 } 0271 0272 if (json.contains("shortenEnd")) { 0273 setShortenEnd(tikz::Value::fromString(json["shortenEnd"].toString())); 0274 } 0275 0276 if (json.contains("textAlign")) { 0277 setTextAlign(toEnum<TextAlignment>(json["textAlign"].toString())); 0278 } 0279 0280 if (json.contains("shape")) { 0281 setShape(toEnum<Shape>(json["shape"].toString())); 0282 } 0283 0284 if (json.contains("minimumWidth")) { 0285 setMinimumWidth(tikz::Value::fromString(json["minimumWidth"].toString())); 0286 } 0287 0288 if (json.contains("minimumHeight")) { 0289 setMinimumHeight(tikz::Value::fromString(json["minimumHeight"].toString())); 0290 } 0291 0292 if (json.contains("innerSep")) { 0293 setInnerSep(tikz::Value::fromString(json["innerSep"].toString())); 0294 } 0295 0296 if (json.contains("outerSep")) { 0297 setOuterSep(tikz::Value::fromString(json["outerSep"].toString())); 0298 } 0299 } 0300 0301 QJsonObject Style::saveData() const 0302 { 0303 QJsonObject json = Entity::saveData(); 0304 0305 json["parentStyle"] = parentStyle().isValid() ? parentStyle().entity<Style>()->uid().toString() : Uid().toString(); 0306 0307 if (penColorSet()) { 0308 json["penColor"] = penColor().name(); 0309 } 0310 0311 if (fillColorSet()) { 0312 json["fillColor"] = fillColor().name(); 0313 } 0314 0315 if (penOpacitySet()) { 0316 json["penOpacity"] = penOpacity(); 0317 } 0318 0319 if (fillOpacitySet()) { 0320 json["fillOpacity"] = fillOpacity(); 0321 } 0322 0323 if (penStyleSet()) { 0324 json["penStyle"] = toString(penStyle()); 0325 } 0326 0327 if (lineWidthSet()) { 0328 json["lineWidth"] = lineWidth().toString(); 0329 } 0330 0331 // FIXME line type 0332 0333 if (doubleLineSet()) { 0334 json["doubleLine"] = doubleLine(); 0335 } 0336 0337 if (innerLineWidthSet()) { 0338 json["innerLineWidth"] = innerLineWidth().toString(); 0339 } 0340 0341 if (innerLineColorSet()) { 0342 json["innerLineColor"] = innerLineColor().name(); 0343 } 0344 0345 if (rotationSet()) { 0346 json["rotation"] = rotation(); 0347 } 0348 0349 if (radiusXSet()) { 0350 json["radiusX"] = radiusX().toString(); 0351 } 0352 0353 if (radiusYSet()) { 0354 json["radiusY"] = radiusY().toString(); 0355 } 0356 0357 if (bendAngleSet()) { 0358 json["bendAngle"] = bendAngle(); 0359 } 0360 0361 if (loosenessSet()) { 0362 json["looseness"] = looseness(); 0363 } 0364 0365 if (outAngleSet()) { 0366 json["outAngle"] = outAngle(); 0367 } 0368 0369 if (inAngleSet()) { 0370 json["inAngle"] = inAngle(); 0371 } 0372 0373 if (arrowTailSet()) { 0374 json["arrowTail"] = toString(arrowTail()); 0375 } 0376 0377 if (arrowHeadSet()) { 0378 json["arrowHead"] = toString(arrowHead()); 0379 } 0380 0381 if (shortenStartSet()) { 0382 json["shortenStart"] = shortenStart().toString(); 0383 } 0384 0385 if (shortenEndSet()) { 0386 json["shortenEnd"] = shortenEnd().toString(); 0387 } 0388 0389 if (textAlignSet()) { 0390 json["textAlign"] = toString(textAlign()); 0391 } 0392 0393 if (shapeSet()) { 0394 json["shape"] = toString(shape()); 0395 } 0396 0397 if (minimumWidthSet()) { 0398 json["minimumWidth"] = minimumWidth().toString(); 0399 } 0400 0401 if (minimumHeightSet()) { 0402 json["minimumHeight"] = minimumHeight().toString(); 0403 } 0404 0405 if (innerSepSet()) { 0406 json["innerSep"] = innerSep().toString(); 0407 } 0408 0409 if (outerSepSet()) { 0410 json["outerSep"] = outerSep().toString(); 0411 } 0412 0413 return json; 0414 } 0415 0416 Uid Style::parentStyle() const 0417 { 0418 return d->parentStyle; 0419 } 0420 0421 void Style::setParentStyle(const Uid & parentUid) 0422 { 0423 if (!uid().isValid()) { 0424 return; 0425 } 0426 0427 if (d->parentStyle != parentUid) { 0428 ConfigTransaction transaction(this); 0429 if (d->parentStyle.isValid()) { 0430 // disconnect all signals (e.g. changed()) 0431 disconnect(d->parentStyle.entity(), nullptr, this, nullptr); 0432 0433 // remove this in old parent's children list 0434 Q_ASSERT(d->parentStyle.entity<Style>()->d->children.contains(uid())); 0435 d->parentStyle.entity<Style>()->d->children.remove(d->parentStyle.entity<Style>()->d->children.indexOf(uid())); 0436 } 0437 d->parentStyle = parentUid; 0438 if (d->parentStyle.isValid()) { 0439 // forward changed() signal 0440 connect(d->parentStyle.entity(), SIGNAL(changed()), this, SIGNAL(changed())); 0441 0442 // insert us into the new parent's children list 0443 Q_ASSERT(! d->parentStyle.entity<Style>()->d->children.contains(uid())); 0444 d->parentStyle.entity<Style>()->d->children.append(uid()); 0445 } 0446 } 0447 } 0448 0449 bool Style::hasChildStyles() const 0450 { 0451 return d->children.size() > 0; 0452 } 0453 0454 void Style::addProperty(const QString & property) 0455 { 0456 d->properties.insert(property); 0457 } 0458 0459 void Style::removeProperty(const QString & property) 0460 { 0461 d->properties.remove(property); 0462 } 0463 0464 bool Style::propertySet(const QString & property) const 0465 { 0466 return d->properties.contains(property); 0467 } 0468 0469 PenStyle Style::penStyle() const 0470 { 0471 if (propertySet(s_penStyle)) { 0472 return d->penStyle; 0473 } 0474 0475 if (parentStyle().isValid()) { 0476 return parentStyle().entity<Style>()->penStyle(); 0477 } 0478 0479 return tikz::PenStyle::SolidLine; 0480 } 0481 0482 bool Style::penStyleSet() const 0483 { 0484 return propertySet(s_penStyle); 0485 } 0486 0487 void Style::setPenStyle(tikz::PenStyle style) 0488 { 0489 if (!propertySet(s_penStyle) || d->penStyle != style) { 0490 ConfigTransaction transaction(this); 0491 addProperty(s_penStyle); 0492 d->penStyle = style; 0493 } 0494 } 0495 0496 void Style::unsetPenStyle() 0497 { 0498 if (propertySet(s_penStyle)) { 0499 ConfigTransaction transaction(this); 0500 removeProperty(s_penStyle); 0501 d->penStyle = tikz::PenStyle::SolidLine; 0502 } 0503 } 0504 0505 tikz::Value Style::penWidth() const 0506 { 0507 if (!doubleLine()) { 0508 return lineWidth(); 0509 } else { 0510 const Value width = lineWidth(); 0511 const Value innerWidth = innerLineWidth(); 0512 return 2.0 * width + innerWidth; 0513 } 0514 } 0515 0516 bool Style::lineWidthSet() const 0517 { 0518 return propertySet(s_lineWidth); 0519 } 0520 0521 void Style::setLineWidth(const tikz::Value & width) 0522 { 0523 if (!propertySet(s_lineWidth) 0524 || d->lineWidth != width 0525 ) { 0526 ConfigTransaction transaction(this); 0527 addProperty(s_lineWidth); 0528 d->lineWidth = width; 0529 } 0530 } 0531 0532 tikz::Value Style::lineWidth() const 0533 { 0534 if (propertySet(s_lineWidth)) { 0535 return d->lineWidth; 0536 } 0537 0538 if (parentStyle().isValid()) { 0539 return parentStyle().entity<Style>()->lineWidth(); 0540 } 0541 0542 return tikz::Value::semiThick(); 0543 } 0544 0545 void Style::unsetLineWidth() 0546 { 0547 if (propertySet(s_lineWidth)) { 0548 ConfigTransaction transaction(this); 0549 removeProperty(s_lineWidth); 0550 d->lineWidth = tikz::Value::semiThick(); 0551 } 0552 } 0553 0554 bool Style::doubleLine() const 0555 { 0556 if (propertySet(s_doubleLine)) { 0557 return d->doubleLine; 0558 } 0559 0560 if (parentStyle().isValid()) { 0561 return parentStyle().entity<Style>()->doubleLine(); 0562 } 0563 0564 return false; 0565 } 0566 0567 bool Style::doubleLineSet() const 0568 { 0569 return propertySet(s_doubleLine); 0570 } 0571 0572 void Style::setDoubleLine(bool enabled) 0573 { 0574 if (!propertySet(s_doubleLine) || d->doubleLine != enabled) { 0575 ConfigTransaction transaction(this); 0576 addProperty(s_doubleLine); 0577 d->doubleLine = enabled; 0578 } 0579 } 0580 0581 void Style::unsetDoubleLine() 0582 { 0583 if (propertySet(s_doubleLine)) { 0584 ConfigTransaction transaction(this); 0585 removeProperty(s_doubleLine); 0586 d->doubleLine = false; 0587 } 0588 } 0589 0590 tikz::Value Style::innerLineWidth() const 0591 { 0592 if (propertySet(s_innerLineWidth)) { 0593 return d->innerLineWidth; 0594 } 0595 0596 if (parentStyle().isValid() && parentStyle().entity<Style>()->doubleLine()) { 0597 return parentStyle().entity<Style>()->innerLineWidth(); 0598 } 0599 0600 return tikz::Value::semiThick(); 0601 } 0602 0603 bool Style::innerLineWidthSet() const 0604 { 0605 return propertySet(s_innerLineWidth); 0606 } 0607 0608 void Style::setInnerLineWidth(const tikz::Value & width) 0609 { 0610 if (!propertySet(s_innerLineWidth) || d->innerLineWidth != width) { 0611 ConfigTransaction transaction(this); 0612 addProperty(s_innerLineWidth); 0613 d->innerLineWidth = width; 0614 } 0615 } 0616 0617 void Style::unsetInnerLineWidth() 0618 { 0619 if (propertySet(s_innerLineWidth)) { 0620 ConfigTransaction transaction(this); 0621 removeProperty(s_innerLineWidth); 0622 d->innerLineWidth = tikz::Value::semiThick(); 0623 } 0624 } 0625 0626 qreal Style::penOpacity() const 0627 { 0628 if (propertySet(s_penOpacity)) { 0629 return d->penOpacity; 0630 } 0631 0632 if (parentStyle().isValid()) { 0633 return parentStyle().entity<Style>()->penOpacity(); 0634 } 0635 0636 return 1.0; 0637 } 0638 0639 void Style::setPenOpacity(qreal opacity) 0640 { 0641 if (!propertySet(s_penOpacity) || d->penOpacity != opacity) { 0642 ConfigTransaction transaction(this); 0643 addProperty(s_penOpacity); 0644 d->penOpacity = opacity; 0645 } 0646 } 0647 0648 bool Style::penOpacitySet() const 0649 { 0650 return propertySet(s_penOpacity); 0651 } 0652 0653 void Style::unsetPenOpacity() 0654 { 0655 if (propertySet(s_penOpacity)) { 0656 ConfigTransaction transaction(this); 0657 removeProperty(s_penOpacity); 0658 d->penOpacity = 1.0; 0659 } 0660 } 0661 0662 qreal Style::fillOpacity() const 0663 { 0664 if (propertySet(s_fillOpacity)) { 0665 return d->fillOpacity; 0666 } 0667 0668 if (parentStyle().isValid()) { 0669 return parentStyle().entity<Style>()->fillOpacity(); 0670 } 0671 0672 return 1.0; 0673 } 0674 0675 bool Style::fillOpacitySet() const 0676 { 0677 return propertySet(s_fillOpacity); 0678 } 0679 0680 void Style::setFillOpacity(qreal opacity) 0681 { 0682 if (!propertySet(s_fillOpacity) || d->fillOpacity != opacity) { 0683 ConfigTransaction transaction(this); 0684 addProperty(s_fillOpacity); 0685 d->fillOpacity = opacity; 0686 } 0687 } 0688 0689 void Style::unsetFillOpacity() 0690 { 0691 if (propertySet(s_fillOpacity)) { 0692 ConfigTransaction transaction(this); 0693 removeProperty(s_fillOpacity); 0694 d->fillOpacity = 1.0; 0695 } 0696 } 0697 0698 QColor Style::penColor() const 0699 { 0700 if (propertySet(s_penColor)) { 0701 return d->penColor; 0702 } 0703 0704 if (parentStyle().isValid()) { 0705 return parentStyle().entity<Style>()->penColor(); 0706 } 0707 0708 return Qt::black; 0709 } 0710 0711 bool Style::penColorSet() const 0712 { 0713 return propertySet(s_penColor); 0714 } 0715 0716 QColor Style::innerLineColor() const 0717 { 0718 if (propertySet(s_innerLineColor)) { 0719 return d->innerLineColor; 0720 } 0721 0722 if (parentStyle().isValid()) { 0723 return parentStyle().entity<Style>()->innerLineColor(); 0724 } 0725 0726 return Qt::white; 0727 } 0728 0729 bool Style::innerLineColorSet() const 0730 { 0731 return propertySet(s_innerLineColor); 0732 } 0733 0734 QColor Style::fillColor() const 0735 { 0736 if (propertySet(s_fillColor)) { 0737 return d->fillColor; 0738 } 0739 0740 if (parentStyle().isValid()) { 0741 return parentStyle().entity<Style>()->fillColor(); 0742 } 0743 0744 return Qt::transparent; 0745 } 0746 0747 bool Style::fillColorSet() const 0748 { 0749 return propertySet(s_fillColor); 0750 } 0751 0752 void Style::setPenColor(const QColor & color) 0753 { 0754 if (!propertySet(s_penColor) || d->penColor != color) { 0755 ConfigTransaction transaction(this); 0756 addProperty(s_penColor); 0757 d->penColor = color; 0758 } 0759 } 0760 0761 void Style::unsetPenColor() 0762 { 0763 if (propertySet(s_penColor)) { 0764 ConfigTransaction transaction(this); 0765 removeProperty(s_penColor); 0766 d->penColor = Qt::black; 0767 } 0768 } 0769 0770 void Style::setInnerLineColor(const QColor & color) 0771 { 0772 if (!propertySet(s_innerLineColor) || d->innerLineColor != color) { 0773 ConfigTransaction transaction(this); 0774 addProperty(s_innerLineColor); 0775 d->innerLineColor = color; 0776 } 0777 } 0778 0779 void Style::unsetInnerLineColor() 0780 { 0781 if (propertySet(s_innerLineColor)) { 0782 ConfigTransaction transaction(this); 0783 removeProperty(s_innerLineColor); 0784 d->innerLineColor = Qt::white; 0785 } 0786 } 0787 0788 void Style::setFillColor(const QColor & color) 0789 { 0790 if (!propertySet(s_fillColor) || d->fillColor != color) { 0791 ConfigTransaction transaction(this); 0792 addProperty(s_fillColor); 0793 d->fillColor = color; 0794 } 0795 } 0796 0797 void Style::unsetFillColor() 0798 { 0799 if (propertySet(s_fillColor)) { 0800 ConfigTransaction transaction(this); 0801 removeProperty(s_fillColor); 0802 d->fillColor = Qt::transparent; 0803 } 0804 } 0805 0806 qreal Style::rotation() const 0807 { 0808 if (propertySet(s_rotation)) { 0809 return d->rotation; 0810 } 0811 0812 if (parentStyle().isValid()) { 0813 return parentStyle().entity<Style>()->rotation(); 0814 } 0815 0816 return 0.0; 0817 } 0818 0819 bool Style::rotationSet() const 0820 { 0821 return propertySet(s_rotation); 0822 } 0823 0824 void Style::setRotation(qreal angle) 0825 { 0826 if (!propertySet(s_rotation) || d->rotation != angle) { 0827 ConfigTransaction transaction(this); 0828 addProperty(s_rotation); 0829 d->rotation = angle; 0830 } 0831 } 0832 0833 void Style::unsetRotation() 0834 { 0835 if (propertySet(s_rotation)) { 0836 ConfigTransaction transaction(this); 0837 removeProperty(s_rotation); 0838 d->rotation = 0.0; 0839 } 0840 } 0841 0842 tikz::Value Style::radiusX() const 0843 { 0844 if (propertySet(s_radiusX)) { 0845 return d->radiusX; 0846 } 0847 0848 auto style = parentStyle().entity<Style>(); 0849 if (style) { 0850 return style->radiusX(); 0851 } 0852 0853 return 0.0_cm; 0854 } 0855 0856 tikz::Value Style::radiusY() const 0857 { 0858 if (propertySet(s_radiusY)) { 0859 return d->radiusY; 0860 } 0861 0862 auto style = parentStyle().entity<Style>(); 0863 if (style) { 0864 return style->radiusY(); 0865 } 0866 0867 return 0.0_cm; 0868 } 0869 0870 bool Style::radiusXSet() const 0871 { 0872 return propertySet(s_radiusX); 0873 } 0874 0875 bool Style::radiusYSet() const 0876 { 0877 return propertySet(s_radiusY); 0878 } 0879 0880 void Style::setRadiusX(const tikz::Value & xradius) 0881 { 0882 if (!propertySet(s_radiusX) || d->radiusX != xradius) { 0883 ConfigTransaction transaction(this); 0884 addProperty(s_radiusX); 0885 d->radiusX = xradius; 0886 } 0887 } 0888 0889 void Style::setRadiusY(const tikz::Value & yradius) 0890 { 0891 if (!propertySet(s_radiusY) || d->radiusY != yradius) { 0892 ConfigTransaction transaction(this); 0893 addProperty(s_radiusY); 0894 d->radiusY = yradius; 0895 } 0896 } 0897 0898 void Style::unsetRadiusX() 0899 { 0900 if (propertySet(s_radiusX)) { 0901 ConfigTransaction transaction(this); 0902 removeProperty(s_radiusX); 0903 d->radiusX = 0.0_cm; 0904 } 0905 } 0906 0907 void Style::unsetRadiusY() 0908 { 0909 if (propertySet(s_radiusY)) { 0910 ConfigTransaction transaction(this); 0911 removeProperty(s_radiusY); 0912 d->radiusY = 0.0_cm; 0913 } 0914 } 0915 0916 qreal Style::bendAngle() const 0917 { 0918 if (propertySet(s_bendAngle)) { 0919 return d->bendAngle; 0920 } 0921 0922 auto style = parentStyle().entity<Style>(); 0923 if (style) { 0924 return style->bendAngle(); 0925 } 0926 0927 return 0.0; 0928 } 0929 0930 bool Style::bendAngleSet() const 0931 { 0932 return propertySet(s_bendAngle); 0933 } 0934 0935 void Style::setBendAngle(qreal angle) 0936 { 0937 // normalize to [-180, 180] 0938 while (angle > 180) angle -= 360.0; 0939 while (angle < -180) angle += 360.0; 0940 0941 if (!propertySet(s_bendAngle) || d->bendAngle != angle) { 0942 ConfigTransaction transaction(this); 0943 addProperty(s_bendAngle); 0944 d->bendAngle = angle; 0945 } 0946 } 0947 0948 void Style::unsetBendAngle() 0949 { 0950 if (propertySet(s_bendAngle)) { 0951 ConfigTransaction transaction(this); 0952 removeProperty(s_bendAngle); 0953 d->bendAngle = 0.0; 0954 } 0955 } 0956 0957 qreal Style::looseness() const 0958 { 0959 if (propertySet(s_looseness)) { 0960 return d->looseness; 0961 } 0962 0963 auto style = parentStyle().entity<Style>(); 0964 if (style) { 0965 return style->looseness(); 0966 } 0967 0968 return 1.0; 0969 } 0970 0971 bool Style::loosenessSet() const 0972 { 0973 return propertySet(s_looseness); 0974 } 0975 0976 void Style::setLooseness(qreal looseness) 0977 { 0978 if (!propertySet(s_looseness) || d->looseness != looseness) { 0979 ConfigTransaction transaction(this); 0980 addProperty(s_looseness); 0981 d->looseness = looseness; 0982 } 0983 } 0984 0985 void Style::unsetLooseness() 0986 { 0987 if (propertySet(s_looseness)) { 0988 ConfigTransaction transaction(this); 0989 removeProperty(s_looseness); 0990 d->looseness = 1.0; 0991 } 0992 } 0993 0994 void Style::setStartControlPoint(const QPointF & cp1) 0995 { 0996 Q_UNUSED(cp1) 0997 // TODO 0998 } 0999 1000 void Style::setEndControlPoint(const QPointF & cp2) 1001 { 1002 Q_UNUSED(cp2) 1003 // TODO 1004 } 1005 1006 QPointF Style::startControlPoint() const 1007 { 1008 return QPointF(); // TODO 1009 } 1010 1011 QPointF Style::endControlPoint() const 1012 { 1013 return QPointF(); // TODO 1014 } 1015 1016 qreal Style::outAngle() const 1017 { 1018 if (propertySet(s_outAngle)) { 1019 return d->outAngle; 1020 } 1021 1022 auto style = parentStyle().entity<Style>(); 1023 if (style) { 1024 return style->outAngle(); 1025 } 1026 1027 return 45; 1028 } 1029 1030 bool Style::outAngleSet() const 1031 { 1032 return propertySet(s_outAngle); 1033 } 1034 1035 void Style::setOutAngle(qreal angle) 1036 { 1037 if (!propertySet(s_outAngle) || d->outAngle != angle) { 1038 ConfigTransaction transaction(this); 1039 addProperty(s_outAngle); 1040 d->outAngle = angle; 1041 } 1042 } 1043 1044 void Style::unsetOutAngle() 1045 { 1046 if (propertySet(s_outAngle)) { 1047 ConfigTransaction transaction(this); 1048 removeProperty(s_outAngle); 1049 d->outAngle = 45; 1050 } 1051 } 1052 1053 qreal Style::inAngle() const 1054 { 1055 if (propertySet(s_inAngle)) { 1056 return d->inAngle; 1057 } 1058 1059 auto style = parentStyle().entity<Style>(); 1060 if (style) { 1061 return style->inAngle(); 1062 } 1063 1064 return 135; 1065 } 1066 1067 bool Style::inAngleSet() const 1068 { 1069 return propertySet(s_inAngle); 1070 } 1071 1072 void Style::setInAngle(qreal angle) 1073 { 1074 if (!propertySet(s_inAngle) || d->inAngle != angle) { 1075 ConfigTransaction transaction(this); 1076 addProperty(s_inAngle); 1077 d->inAngle = angle; 1078 } 1079 } 1080 1081 void Style::unsetInAngle() 1082 { 1083 if (propertySet(s_inAngle)) { 1084 ConfigTransaction transaction(this); 1085 removeProperty(s_inAngle); 1086 d->inAngle = 135; 1087 } 1088 } 1089 1090 Arrow Style::arrowTail() const 1091 { 1092 if (propertySet(s_arrowTail)) { 1093 return d->arrowTail; 1094 } 1095 1096 auto style = parentStyle().entity<Style>(); 1097 if (style) { 1098 return style->arrowTail(); 1099 } 1100 1101 return tikz::Arrow::NoArrow; 1102 } 1103 1104 bool Style::arrowTailSet() const 1105 { 1106 return propertySet(s_arrowTail); 1107 } 1108 1109 Arrow Style::arrowHead() const 1110 { 1111 if (propertySet(s_arrowHead)) { 1112 return d->arrowHead; 1113 } 1114 1115 auto style = parentStyle().entity<Style>(); 1116 if (style) { 1117 return style->arrowHead(); 1118 } 1119 1120 return tikz::Arrow::NoArrow; 1121 } 1122 1123 bool Style::arrowHeadSet() const 1124 { 1125 return propertySet(s_arrowHead); 1126 } 1127 1128 void Style::setArrowTail(tikz::Arrow tail) 1129 { 1130 if (!propertySet(s_arrowTail) || d->arrowTail != tail) { 1131 ConfigTransaction transaction(this); 1132 addProperty(s_arrowTail); 1133 d->arrowTail = tail; 1134 } 1135 } 1136 1137 void Style::setArrowHead(tikz::Arrow head) 1138 { 1139 if (!propertySet(s_arrowHead) || d->arrowHead != head) { 1140 ConfigTransaction transaction(this); 1141 addProperty(s_arrowHead); 1142 d->arrowHead = head; 1143 } 1144 } 1145 1146 void Style::unsetArrowTail() 1147 { 1148 if (propertySet(s_arrowTail)) { 1149 ConfigTransaction transaction(this); 1150 removeProperty(s_arrowTail); 1151 d->arrowTail = tikz::Arrow::NoArrow; 1152 } 1153 } 1154 1155 void Style::unsetArrowHead() 1156 { 1157 if (propertySet(s_arrowHead)) { 1158 ConfigTransaction transaction(this); 1159 removeProperty(s_arrowHead); 1160 d->arrowHead = tikz::Arrow::NoArrow; 1161 } 1162 } 1163 1164 tikz::Value Style::shortenStart() const 1165 { 1166 if (propertySet(s_shortenStart)) { 1167 return d->shortenStart; 1168 } 1169 1170 auto style = parentStyle().entity<Style>(); 1171 if (style) { 1172 return style->shortenStart(); 1173 } 1174 1175 return 0.0_cm; 1176 } 1177 1178 bool Style::shortenStartSet() const 1179 { 1180 return propertySet(s_shortenStart); 1181 } 1182 1183 tikz::Value Style::shortenEnd() const 1184 { 1185 if (propertySet(s_shortenEnd)) { 1186 return d->shortenEnd; 1187 } 1188 1189 auto style = parentStyle().entity<Style>(); 1190 if (style) { 1191 return style->shortenEnd(); 1192 } 1193 1194 return 0.0_cm; 1195 } 1196 1197 bool Style::shortenEndSet() const 1198 { 1199 return propertySet(s_shortenEnd); 1200 } 1201 1202 void Style::setShortenStart(const tikz::Value & shorten) 1203 { 1204 if (!propertySet(s_shortenStart) || d->shortenStart != shorten) { 1205 ConfigTransaction transaction(this); 1206 addProperty(s_shortenStart); 1207 d->shortenStart = shorten; 1208 } 1209 } 1210 1211 void Style::setShortenEnd(const tikz::Value & shorten) 1212 { 1213 if (!propertySet(s_shortenEnd) || d->shortenEnd != shorten) { 1214 ConfigTransaction transaction(this); 1215 addProperty(s_shortenEnd); 1216 d->shortenEnd = shorten; 1217 } 1218 } 1219 1220 void Style::unsetShortenStart() 1221 { 1222 if (propertySet(s_shortenStart)) { 1223 ConfigTransaction transaction(this); 1224 removeProperty(s_shortenStart); 1225 d->shortenStart = 0.0_cm; 1226 } 1227 } 1228 1229 void Style::unsetShortenEnd() 1230 { 1231 if (propertySet(s_shortenEnd)) { 1232 ConfigTransaction transaction(this); 1233 removeProperty(s_shortenEnd); 1234 d->shortenEnd = 0.0_cm; 1235 } 1236 } 1237 1238 TextAlignment Style::textAlign() const 1239 { 1240 if (propertySet(s_align)) { 1241 return d->textAlign; 1242 } 1243 1244 auto style = parentStyle().entity<Style>(); 1245 if (style) { 1246 return style->textAlign(); 1247 } 1248 1249 return TextAlignment::NoAlign; 1250 } 1251 1252 bool Style::textAlignSet() const 1253 { 1254 return propertySet(s_align); 1255 } 1256 1257 void Style::setTextAlign(tikz::TextAlignment align) 1258 { 1259 if (!propertySet(s_align) || d->textAlign != align) { 1260 ConfigTransaction transaction(this); 1261 addProperty(s_align); 1262 d->textAlign = align; 1263 } 1264 } 1265 1266 void Style::unsetTextAlign() 1267 { 1268 if (propertySet(s_align)) { 1269 ConfigTransaction transaction(this); 1270 removeProperty(s_align); 1271 d->textAlign = TextAlignment::NoAlign; 1272 } 1273 } 1274 1275 Shape Style::shape() const 1276 { 1277 if (propertySet(s_shape)) { 1278 return d->shape; 1279 } 1280 1281 auto style = parentStyle().entity<Style>(); 1282 if (style) { 1283 return style->shape(); 1284 } 1285 1286 return Shape::ShapeRectangle; 1287 } 1288 1289 bool Style::shapeSet() const 1290 { 1291 return propertySet(s_shape); 1292 } 1293 1294 void Style::setShape(tikz::Shape shape) 1295 { 1296 if (!propertySet(s_shape) || d->shape != shape) { 1297 ConfigTransaction transaction(this); 1298 addProperty(s_shape); 1299 d->shape = shape; 1300 } 1301 } 1302 1303 void Style::unsetShape() 1304 { 1305 if (propertySet(s_shape)) { 1306 ConfigTransaction transaction(this); 1307 removeProperty(s_shape); 1308 d->shape = Shape::ShapeRectangle; 1309 } 1310 } 1311 1312 void Style::setInnerSep(const tikz::Value & sep) 1313 { 1314 if (!propertySet(s_innerSep) || d->innerSep != sep) { 1315 ConfigTransaction transaction(this); 1316 addProperty(s_innerSep); 1317 d->innerSep = sep; 1318 } 1319 } 1320 1321 bool Style::innerSepSet() const 1322 { 1323 return propertySet(s_innerSep); 1324 } 1325 1326 tikz::Value Style::innerSep() const 1327 { 1328 auto style = parentStyle().entity<Style>(); 1329 if (!propertySet(s_innerSep) && style) { 1330 return style->innerSep(); 1331 } 1332 return d->innerSep; 1333 } 1334 1335 void Style::setOuterSep(const tikz::Value & sep) 1336 { 1337 if (!propertySet(s_outerSep) || d->outerSep != sep) { 1338 ConfigTransaction transaction(this); 1339 addProperty(s_outerSep); 1340 d->outerSep = sep; 1341 } 1342 } 1343 1344 bool Style::outerSepSet() const 1345 { 1346 return propertySet(s_outerSep); 1347 } 1348 1349 tikz::Value Style::outerSep() const 1350 { 1351 if (!propertySet(s_outerSep)) { 1352 return 0.5 * penWidth(); 1353 } 1354 return d->outerSep; 1355 } 1356 1357 void Style::unsetInnerSep() 1358 { 1359 if (propertySet(s_innerSep)) { 1360 ConfigTransaction transaction(this); 1361 removeProperty(s_innerSep); 1362 d->innerSep = 3.0_pt; //FIXME: 0.3333em 1363 } 1364 } 1365 1366 void Style::unsetOuterSep() 1367 { 1368 if (propertySet(s_outerSep)) { 1369 ConfigTransaction transaction(this); 1370 removeProperty(s_outerSep); 1371 d->outerSep = 3.0_pt; //FIXME: 0.3333em 1372 } 1373 } 1374 1375 tikz::Value Style::minimumHeight() const 1376 { 1377 if (propertySet(s_minimumHeight)) { 1378 return d->minimumHeight; 1379 } 1380 1381 auto style = parentStyle().entity<Style>(); 1382 if (style) { 1383 return style->minimumHeight(); 1384 } 1385 1386 return 0.0_cm; 1387 } 1388 1389 bool Style::minimumHeightSet() const 1390 { 1391 return propertySet(s_minimumHeight); 1392 } 1393 1394 tikz::Value Style::minimumWidth() const 1395 { 1396 if (propertySet(s_minimumWidth)) { 1397 return d->minimumWidth; 1398 } 1399 1400 auto style = parentStyle().entity<Style>(); 1401 if (style) { 1402 return style->minimumWidth(); 1403 } 1404 1405 return 0.0_cm; 1406 } 1407 1408 bool Style::minimumWidthSet() const 1409 { 1410 return propertySet(s_minimumWidth); 1411 } 1412 1413 void Style::setMinimumHeight(const tikz::Value & height) 1414 { 1415 if (!propertySet(s_minimumHeight) || d->minimumHeight != height) { 1416 ConfigTransaction transaction(this); 1417 addProperty(s_minimumHeight); 1418 d->minimumHeight = height; 1419 } 1420 } 1421 1422 void Style::setMinimumWidth(const tikz::Value & width) 1423 { 1424 if (!propertySet(s_minimumWidth) || d->minimumWidth != width) { 1425 ConfigTransaction transaction(this); 1426 addProperty(s_minimumWidth); 1427 d->minimumWidth = width; 1428 } 1429 } 1430 1431 void Style::unsetMinimumHeight() 1432 { 1433 if (propertySet(s_minimumHeight)) { 1434 ConfigTransaction transaction(this); 1435 removeProperty(s_minimumHeight); 1436 d->minimumHeight = 0.0_cm; 1437 } 1438 } 1439 1440 void Style::unsetMinimumWidth() 1441 { 1442 if (propertySet(s_minimumWidth)) { 1443 ConfigTransaction transaction(this); 1444 removeProperty(s_minimumWidth); 1445 d->minimumWidth = 0.0_cm; 1446 } 1447 } 1448 1449 1450 } 1451 } 1452 1453 // kate: indent-width 4; replace-tabs on;