File indexing completed on 2025-02-02 12:45:36
0001 /*************************************************************************** 0002 * Copyright (C) 2005,2006 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "dpline.h" 0012 #include "libraryitem.h" 0013 #include "resizeoverlay.h" 0014 #include "variant.h" 0015 0016 #include <KLocalizedString> 0017 #include <QPainter> 0018 #include <cmath> 0019 #include <cstdlib> 0020 0021 // BEGIN class DPLine 0022 Item *DPLine::construct(ItemDocument *itemDocument, bool newItem, const char *id) 0023 { 0024 return new DPLine(itemDocument, newItem, id); 0025 } 0026 0027 LibraryItem *DPLine::libraryItem() 0028 { 0029 return new LibraryItem(QStringList(QString("dp/line")), i18n("Line"), i18n("Other"), QIcon::fromTheme("text"), LibraryItem::lit_drawpart, DPLine::construct); 0030 } 0031 0032 DPLine::DPLine(ItemDocument *itemDocument, bool newItem, const char *id) 0033 : DrawPart(itemDocument, newItem, id ? id : "line") 0034 { 0035 m_pLineOverlay = new LineOverlay(this); 0036 m_name = i18n("Line"); 0037 0038 createProperty("line-color", Variant::Type::Color); 0039 property("line-color")->setCaption(i18n("Line Color")); 0040 property("line-color")->setValue(QColor(Qt::black)); 0041 0042 createProperty("line-width", Variant::Type::Int); 0043 property("line-width")->setCaption(i18n("Line Width")); 0044 property("line-width")->setMinValue(1); 0045 property("line-width")->setMaxValue(1000); 0046 property("line-width")->setValue(1); 0047 0048 createProperty("line-style", Variant::Type::PenStyle); 0049 property("line-style")->setCaption(i18n("Line Style")); 0050 property("line-style")->setAdvanced(true); 0051 setDataPenStyle("line-style", Qt::SolidLine); 0052 0053 createProperty("cap-style", Variant::Type::PenCapStyle); 0054 property("cap-style")->setCaption(i18n("Cap Style")); 0055 property("cap-style")->setAdvanced(true); 0056 setDataPenCapStyle("cap-style", Qt::FlatCap); 0057 } 0058 0059 DPLine::~DPLine() 0060 { 0061 } 0062 0063 void DPLine::setSelected(bool yes) 0064 { 0065 if (yes == isSelected()) 0066 return; 0067 0068 DrawPart::setSelected(yes); 0069 m_pLineOverlay->showResizeHandles(yes); 0070 } 0071 0072 void DPLine::dataChanged() 0073 { 0074 setPen(QPen(dataColor("line-color"), unsigned(dataInt("line-width")), getDataPenStyle("line-style"), getDataPenCapStyle("cap-style"), Qt::MiterJoin)); 0075 0076 postResize(); // in case the pen width has changed 0077 update(); 0078 } 0079 0080 void DPLine::postResize() 0081 { 0082 int x1 = offsetX(); 0083 int y1 = offsetY(); 0084 int x2 = x1 + width(); 0085 int y2 = y1 + height(); 0086 0087 QPolygon p(4); 0088 int pw = pen().width(); 0089 int dx = abs(x1 - x2); 0090 int dy = abs(y1 - y2); 0091 pw = pw * 4 / 3 + 2; // approx pw*sqrt(2) 0092 int px = x1 < x2 ? -pw : pw; 0093 int py = y1 < y2 ? -pw : pw; 0094 if (dx && dy && (dx > dy ? (dx * 2 / dy <= 2) : (dy * 2 / dx <= 2))) { 0095 // steep 0096 if (px == py) { 0097 p[0] = QPoint(x1, y1 + py); 0098 p[1] = QPoint(x2 - px, y2); 0099 p[2] = QPoint(x2, y2 - py); 0100 p[3] = QPoint(x1 + px, y1); 0101 } else { 0102 p[0] = QPoint(x1 + px, y1); 0103 p[1] = QPoint(x2, y2 - py); 0104 p[2] = QPoint(x2 - px, y2); 0105 p[3] = QPoint(x1, y1 + py); 0106 } 0107 } else if (dx > dy) { 0108 // horizontal 0109 p[0] = QPoint(x1 + px, y1 + py); 0110 p[1] = QPoint(x2 - px, y2 + py); 0111 p[2] = QPoint(x2 - px, y2 - py); 0112 p[3] = QPoint(x1 + px, y1 - py); 0113 } else { 0114 // vertical 0115 p[0] = QPoint(x1 + px, y1 + py); 0116 p[1] = QPoint(x2 + px, y2 - py); 0117 p[2] = QPoint(x2 - px, y2 - py); 0118 p[3] = QPoint(x1 - px, y1 + py); 0119 } 0120 setItemPoints(p, false); 0121 } 0122 0123 void DPLine::drawShape(QPainter &p) 0124 { 0125 int x1 = int(x() + offsetX()); 0126 int y1 = int(y() + offsetY()); 0127 int x2 = x1 + width(); 0128 int y2 = y1 + height(); 0129 0130 p.drawLine(x1, y1, x2, y2); 0131 } 0132 // END class DPLine 0133 0134 // BEGIN class DPArrow 0135 Item *DPArrow::construct(ItemDocument *itemDocument, bool newItem, const char *id) 0136 { 0137 return new DPArrow(itemDocument, newItem, id); 0138 } 0139 0140 LibraryItem *DPArrow::libraryItem() 0141 { 0142 return new LibraryItem(QStringList(QString("dp/arrow")), i18n("Arrow"), i18n("Other"), QIcon::fromTheme("text"), LibraryItem::lit_drawpart, DPArrow::construct); 0143 } 0144 0145 DPArrow::DPArrow(ItemDocument *itemDocument, bool newItem, const char *id) 0146 : DPLine(itemDocument, newItem, id ? id : "arrow") 0147 { 0148 m_name = i18n("Arrow"); 0149 0150 // We don't want to use the square cap style as it screws up drawing our arrow head 0151 QStringList allowed = property("cap-style")->allowed(); 0152 allowed.removeAll(DrawPart::penCapStyleToName(Qt::SquareCap)); 0153 property("cap-style")->setAllowed(allowed); 0154 0155 m_headAngle = 20.0; 0156 Variant *v = createProperty("HeadAngle", Variant::Type::Double); 0157 v->setAdvanced(true); 0158 v->setCaption(i18n("Head angle")); 0159 v->setMinValue(10.0); 0160 v->setMaxValue(60.0); 0161 v->setUnit(QChar(0xb0)); 0162 v->setValue(m_headAngle); 0163 } 0164 0165 DPArrow::~DPArrow() 0166 { 0167 } 0168 0169 void DPArrow::dataChanged() 0170 { 0171 DPLine::dataChanged(); 0172 m_headAngle = dataDouble("HeadAngle"); 0173 setChanged(); 0174 } 0175 0176 inline int round_x(double x) 0177 { 0178 return int(x + ((x > 0) ? 0.5 : -0.5)); 0179 } 0180 0181 void DPArrow::drawShape(QPainter &p) 0182 { 0183 double x1 = x() + offsetX(); 0184 double y1 = y() + offsetY(); 0185 double x2 = x1 + width(); 0186 double y2 = y1 + height(); 0187 0188 p.drawLine(int(x1), int(y1), int(x2), int(y2)); 0189 0190 double dx = x2 - x1; 0191 double dy = y2 - y1; 0192 0193 if (dx == 0. && dy == 0.) 0194 return; 0195 0196 double arrow_angle = (dx == 0 ? (dy > 0 ? (M_PI_2) : (-M_PI_2)) : std::atan(dy / dx)); 0197 if (dx < 0) 0198 arrow_angle += M_PI; 0199 0200 double head_angle = M_PI * m_headAngle / 180.0; 0201 double head_length = 10.0; 0202 0203 // Position of arrowhead 0204 double x3 = x2 + head_length * std::cos(M_PI + arrow_angle - head_angle); 0205 double y3 = y2 + head_length * std::sin(M_PI + arrow_angle - head_angle); 0206 double x4 = x2 + head_length * std::cos(M_PI + arrow_angle + head_angle); 0207 double y4 = y2 + head_length * std::sin(M_PI + arrow_angle + head_angle); 0208 0209 // Draw arrowhead 0210 QPen pen = p.pen(); 0211 pen.setCapStyle(Qt::RoundCap); 0212 p.setPen(pen); 0213 p.setBrush(pen.color()); 0214 QPolygon pa(3); 0215 pa[0] = QPoint(round_x(x2), round_x(y2)); 0216 pa[1] = QPoint(round_x(x3), round_x(y3)); 0217 pa[2] = QPoint(round_x(x4), round_x(y4)); 0218 p.drawPolygon(pa); 0219 p.drawPolyline(pa); 0220 } 0221 // END class DPLine