tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / libreofficekit / qa / gtktiledviewer / gtv-calc-header-bar.cxx
blob6019050236e8e943e3d97e8915c7526bbdd558cf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <gtk/gtk.h>
12 #include <cmath>
13 #include <iostream>
14 #include <vector>
16 #include "gtv-calc-header-bar.hxx"
18 #include <boost/property_tree/ptree.hpp>
19 #include <o3tl/unreachable.hxx>
20 #include <utility>
22 namespace {
24 struct GtvCalcHeaderBarPrivateImpl
26 /// Stores size and content of a single row header.
27 struct Header
29 int m_nSize;
30 std::string m_aText;
31 Header(int nSize, std::string aText)
32 : m_nSize(nSize),
33 m_aText(std::move(aText))
34 { }
37 std::vector<Header> m_aHeaders;
38 CalcHeaderType m_eType;
40 GtvCalcHeaderBarPrivateImpl()
41 : m_eType(CalcHeaderType::NONE)
42 { }
45 struct GtvCalcHeaderBarPrivate
47 GtvCalcHeaderBarPrivateImpl* m_pImpl;
49 GtvCalcHeaderBarPrivateImpl* operator->()
51 return m_pImpl;
57 #if defined __clang__
58 #if __has_warning("-Wdeprecated-volatile")
59 #pragma clang diagnostic push
60 #pragma clang diagnostic ignored "-Wdeprecated-volatile"
61 #endif
62 #endif
63 G_DEFINE_TYPE_WITH_PRIVATE(GtvCalcHeaderBar, gtv_calc_header_bar, GTK_TYPE_DRAWING_AREA);
64 #if defined __clang__
65 #if __has_warning("-Wdeprecated-volatile")
66 #pragma clang diagnostic pop
67 #endif
68 #endif
70 const int ROW_HEADER_WIDTH = 50;
71 const int COLUMN_HEADER_HEIGHT = 20;
73 static GtvCalcHeaderBarPrivate&
74 getPrivate(GtvCalcHeaderBar* headerbar)
76 return *static_cast<GtvCalcHeaderBarPrivate*>(gtv_calc_header_bar_get_instance_private(headerbar));
79 static void
80 gtv_calc_header_bar_init(GtvCalcHeaderBar* bar)
82 GtvCalcHeaderBarPrivate& priv = getPrivate(bar);
83 priv.m_pImpl = new GtvCalcHeaderBarPrivateImpl();
86 static void
87 gtv_calc_header_bar_finalize(GObject* object)
89 GtvCalcHeaderBarPrivate& priv = getPrivate(GTV_CALC_HEADER_BAR(object));
91 delete priv.m_pImpl;
92 priv.m_pImpl = nullptr;
94 G_OBJECT_CLASS (gtv_calc_header_bar_parent_class)->finalize (object);
97 static void gtv_calc_header_bar_draw_text(cairo_t* pCairo, const GdkRectangle& rRectangle, const std::string& rText)
99 cairo_text_extents_t extents;
100 cairo_text_extents(pCairo, rText.c_str(), &extents);
101 // Cairo reference point for text is the bottom left corner.
102 cairo_move_to(pCairo, rRectangle.x + rRectangle.width / 2 - extents.width / 2, rRectangle.y + rRectangle.height / 2 + extents.height / 2);
103 cairo_show_text(pCairo, rText.c_str());
106 static bool gtv_calc_header_bar_draw_impl(GtkWidget* pWidget, cairo_t* pCairo)
108 GtvCalcHeaderBar* self = GTV_CALC_HEADER_BAR(pWidget);
109 GtvCalcHeaderBarPrivate& priv = getPrivate(GTV_CALC_HEADER_BAR(self));
110 cairo_set_source_rgb(pCairo, 0, 0, 0);
112 int nPrevious = 0;
113 for (const GtvCalcHeaderBarPrivateImpl::Header& rHeader : priv->m_aHeaders)
115 GdkRectangle aRectangle;
116 if (priv->m_eType == CalcHeaderType::ROW)
118 aRectangle.x = 0;
119 aRectangle.y = nPrevious;
120 aRectangle.width = ROW_HEADER_WIDTH - 1;
121 aRectangle.height = rHeader.m_nSize - nPrevious;
122 // Left line.
123 cairo_rectangle(pCairo, aRectangle.x, aRectangle.y, 1, aRectangle.height);
124 cairo_fill(pCairo);
125 // Bottom line.
126 cairo_rectangle(pCairo, aRectangle.x, aRectangle.y + aRectangle.height, aRectangle.width, 1);
127 cairo_fill(pCairo);
128 // Right line.
129 cairo_rectangle(pCairo, aRectangle.width, aRectangle.y, 1, aRectangle.height);
130 cairo_fill(pCairo);
132 else if (priv->m_eType == CalcHeaderType::COLUMN)
134 aRectangle.x = nPrevious;
135 aRectangle.y = 0;
136 aRectangle.width = rHeader.m_nSize - nPrevious;
137 aRectangle.height = COLUMN_HEADER_HEIGHT - 1;
138 // Top line.
139 cairo_rectangle(pCairo, aRectangle.x, aRectangle.y, aRectangle.width, 1);
140 cairo_fill(pCairo);
141 // Right line.
142 cairo_rectangle(pCairo, aRectangle.x + aRectangle.width , aRectangle.y, 1, aRectangle.height);
143 cairo_fill(pCairo);
144 // Bottom line.
145 cairo_rectangle(pCairo, aRectangle.x, aRectangle.height, aRectangle.width, 1);
146 cairo_fill(pCairo);
148 else
150 O3TL_UNREACHABLE; // should never happen
153 gtv_calc_header_bar_draw_text(pCairo, aRectangle, rHeader.m_aText);
154 nPrevious = rHeader.m_nSize;
155 if (rHeader.m_nSize > self->m_nSizePixel)
156 break;
159 if (priv->m_aHeaders.empty() && priv->m_eType == CalcHeaderType::CORNER)
161 GdkRectangle aRectangle;
162 aRectangle.x = 0;
163 aRectangle.y = 0;
164 aRectangle.width = ROW_HEADER_WIDTH - 1;
165 aRectangle.height = COLUMN_HEADER_HEIGHT - 1;
166 cairo_rectangle(pCairo, aRectangle.x, aRectangle.y, aRectangle.width, aRectangle.height);
167 cairo_stroke(pCairo);
170 return false;
173 static gboolean
174 gtv_calc_header_bar_draw(GtkWidget* bar, cairo_t* pCairo)
176 return gtv_calc_header_bar_draw_impl(bar, pCairo);
179 static void
180 gtv_calc_header_bar_class_init(GtvCalcHeaderBarClass* klass)
182 GTK_WIDGET_CLASS(klass)->draw = gtv_calc_header_bar_draw;
183 G_OBJECT_CLASS(klass)->finalize = gtv_calc_header_bar_finalize;
186 void gtv_calc_header_bar_configure(GtvCalcHeaderBar* bar, const boost::property_tree::ptree* values)
188 GtvCalcHeaderBarPrivate& priv = getPrivate(bar);
189 priv->m_aHeaders.clear();
191 if (values)
193 boost::property_tree::ptree val = *values;
196 for (const boost::property_tree::ptree::value_type& rValue : val)
198 int nSize = std::round(std::atof(rValue.second.get<std::string>("size").c_str()));
199 if (nSize >= bar->m_nPositionPixel)
201 const int nScrolledSize = nSize - bar->m_nPositionPixel;
202 GtvCalcHeaderBarPrivateImpl::Header aHeader(nScrolledSize, rValue.second.get<std::string>("text"));
203 priv->m_aHeaders.push_back(aHeader);
207 catch (boost::property_tree::ptree_bad_path& rException)
209 std::cerr << "gtv_calc_header_bar_configure: " << rException.what() << std::endl;
212 gtk_widget_show(GTK_WIDGET(bar));
213 gtk_widget_queue_draw(GTK_WIDGET(bar));
216 void
217 gtv_calc_header_bar_set_type_and_width(GtvCalcHeaderBar* bar, CalcHeaderType eType)
219 // TODO: Install type property for this class
220 GtvCalcHeaderBarPrivate& priv = getPrivate(bar);
221 priv->m_eType = eType;
223 if (eType == CalcHeaderType::ROW)
224 gtk_widget_set_size_request(GTK_WIDGET(bar), ROW_HEADER_WIDTH, -1);
225 else if (eType == CalcHeaderType::COLUMN)
226 gtk_widget_set_size_request(GTK_WIDGET(bar), -1, COLUMN_HEADER_HEIGHT);
229 GtkWidget*
230 gtv_calc_header_bar_new()
232 return GTK_WIDGET(g_object_new(GTV_TYPE_CALC_HEADER_BAR,
233 nullptr));
236 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */