|
1 | 1 | #include "aotextboxwidgets.h" |
2 | 2 |
|
| 3 | +// Sane outlined QLabel solution ported from PyQt solution on StackOverflow by alec |
| 4 | +// https://stackoverflow.com/questions/64290561/qlabel-correct-positioning-for-text-outline |
| 5 | + |
3 | 6 | AOChatboxLabel::AOChatboxLabel(QWidget *parent) |
4 | 7 | : QLabel(parent) |
5 | | -{} |
| 8 | +{ |
| 9 | + setBrush(QBrush(Qt::white)); |
| 10 | + setPen(QPen(Qt::black)); |
| 11 | +} |
6 | 12 |
|
7 | | -void AOChatboxLabel::setOutlineColor(QColor color) |
| 13 | +void AOChatboxLabel::setIsOutlined(bool outlined) |
8 | 14 | { |
9 | | - m_outline_color = color; |
| 15 | + m_outline = outlined; |
10 | 16 | } |
11 | 17 |
|
12 | | -void AOChatboxLabel::setOutlineWidth(int width) |
| 18 | +bool AOChatboxLabel::pointMode() |
13 | 19 | { |
14 | | - m_outline_width = width; |
| 20 | + return m_pointmode; |
15 | 21 | } |
16 | 22 |
|
17 | | -void AOChatboxLabel::setIsOutlined(bool outlined) |
| 23 | +void AOChatboxLabel::setPointMode(bool mode) |
18 | 24 | { |
19 | | - m_outline = outlined; |
| 25 | + m_pointmode = mode; |
| 26 | +} |
| 27 | + |
| 28 | +double AOChatboxLabel::outlineThickness() |
| 29 | +{ |
| 30 | + if (pointMode()) |
| 31 | + { |
| 32 | + return m_outline_width * font().pointSize(); |
| 33 | + } |
| 34 | + else |
| 35 | + return m_outline_width; |
| 36 | +} |
| 37 | + |
| 38 | +void AOChatboxLabel::setOutlineThickness(double w) |
| 39 | +{ |
| 40 | + m_outline_width = w; |
| 41 | +} |
| 42 | + |
| 43 | +void AOChatboxLabel::setBrush(QBrush brush) |
| 44 | +{ |
| 45 | + m_brush = brush; |
| 46 | +} |
| 47 | +void AOChatboxLabel::setPen(QPen pen) |
| 48 | +{ |
| 49 | + m_pen = pen; |
20 | 50 | } |
21 | 51 |
|
22 | | -void AOChatboxLabel::setTextColor(QColor color) |
| 52 | +QSize AOChatboxLabel::sizeHint() |
23 | 53 | { |
24 | | - m_text_color = color; |
| 54 | + int nrml_w = std::ceil(outlineThickness() * 2); |
| 55 | + return QLabel::sizeHint() + QSize(nrml_w, nrml_w); |
| 56 | +} |
| 57 | +QSize AOChatboxLabel::minimumSizeHint() |
| 58 | +{ |
| 59 | + int nrml_w = std::ceil(outlineThickness() * 2); |
| 60 | + return QLabel::minimumSizeHint() + QSize(nrml_w, nrml_w); |
25 | 61 | } |
26 | 62 |
|
27 | 63 | void AOChatboxLabel::paintEvent(QPaintEvent *event) |
28 | 64 | { |
29 | 65 | if (m_outline) |
30 | 66 | { |
31 | | - QBrush brush; |
32 | | - QPen pen; |
33 | | - QPointF baseline(m_outline_width, fontMetrics().height()); |
| 67 | + double w = outlineThickness(); |
| 68 | + QRectF rect = this->rect(); |
| 69 | + QFontMetrics metrics = QFontMetrics(this->font()); |
| 70 | + QRect tr = metrics.boundingRect(text()).adjusted(0, 0, w, w); |
| 71 | + int l_indent; |
| 72 | + int x; |
| 73 | + int y; |
| 74 | + |
| 75 | + if (indent() == -1) |
| 76 | + { |
| 77 | + if (frameWidth()) |
| 78 | + { |
| 79 | + l_indent = (metrics.boundingRect("x").width() + w * 2) / 2; |
| 80 | + } |
| 81 | + else |
| 82 | + { |
| 83 | + l_indent = w; |
| 84 | + } |
| 85 | + } |
| 86 | + else |
| 87 | + { |
| 88 | + l_indent = indent(); |
| 89 | + } |
34 | 90 |
|
35 | | - // Set up brush (base text) |
36 | | - brush.setColor(m_text_color); |
37 | | - brush.setStyle(Qt::SolidPattern); |
| 91 | + if (alignment() & Qt::AlignLeft) |
| 92 | + { |
| 93 | + x = rect.left() + l_indent - std::min(metrics.leftBearing(text()[0]), 0); |
| 94 | + } |
| 95 | + else if (alignment() & Qt::AlignRight) |
| 96 | + { |
| 97 | + x = rect.x() + rect.width() - l_indent - tr.width(); |
| 98 | + } |
| 99 | + else |
| 100 | + { |
| 101 | + x = (rect.width() - tr.width()) / 2; |
| 102 | + } |
38 | 103 |
|
39 | | - // Set up outline |
40 | | - pen.setColor(m_outline_color); |
41 | | - pen.setWidthF(m_outline_width); |
| 104 | + if (alignment() & Qt::AlignTop) |
| 105 | + { |
| 106 | + y = rect.top() + l_indent + metrics.ascent(); |
| 107 | + } |
| 108 | + else if (alignment() & Qt::AlignBottom) |
| 109 | + { |
| 110 | + y = rect.y() + rect.height() - l_indent - metrics.descent(); |
| 111 | + } |
| 112 | + else |
| 113 | + { |
| 114 | + y = (rect.height() + metrics.ascent() - metrics.descent()) / 2; |
| 115 | + } |
42 | 116 |
|
| 117 | + m_pen.setWidth(w * 2); |
43 | 118 | QPainterPath path; |
44 | | - path.addText(baseline, font(), text()); |
| 119 | + path.addText(x, y, font(), text()); |
45 | 120 |
|
46 | 121 | QPainter painter(this); |
47 | 122 | painter.setRenderHint(QPainter::Antialiasing); |
48 | | - // draw outline |
49 | | - painter.setPen(pen); |
50 | | - painter.drawPath(path); |
51 | | - // remove outline pen, then draw text on top |
52 | | - painter.setPen(Qt::NoPen); |
53 | | - painter.setBrush(brush); |
54 | | - painter.drawPath(path); |
| 123 | + painter.strokePath(path, m_pen); |
| 124 | + if (1 < m_brush.style() && m_brush.style() < 15) |
| 125 | + painter.fillPath(path, palette().window()); |
| 126 | + painter.fillPath(path, m_brush); |
55 | 127 | } |
56 | 128 | else |
57 | 129 | { |
|
0 commit comments