@@ -39,17 +39,19 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
39
39
label_.set_width_chars (config_[" min-length" ].asUInt ());
40
40
}
41
41
42
- uint rotate = 0 ;
43
42
if (config_[" rotate" ].isUInt ()) {
44
- rotate = config[" rotate" ].asUInt ();
45
- if (not (rotate == 0 || rotate == 90 || rotate == 180 || rotate == 270 ))
46
- spdlog::error (" 'rotate' is only supported in 90 degree increments {} is not valid." , rotate);
47
- // TODO
43
+ rotate_ = config[" rotate" ].asUInt () % 360 ;
44
+ if (not (rotate_ == 0 || rotate_ == 90 || rotate_ == 180 || rotate_ == 270 )) {
45
+ spdlog::error (
46
+ " 'rotate' is only supported in 90 degree increments {} is not valid. Falling back to 0." ,
47
+ rotate_);
48
+ rotate_ = 0 ;
49
+ }
48
50
}
49
51
50
52
if (config_[" align" ].isDouble ()) {
51
53
auto align = config_[" align" ].asFloat ();
52
- if (rotate == 90 || rotate == 270 ) {
54
+ if (rotate_ == 90 || rotate_ == 270 ) {
53
55
label_.set_yalign (align);
54
56
} else {
55
57
label_.set_xalign (align);
@@ -235,21 +237,68 @@ Gtk::Widget& ALabel::child() {
235
237
return const_cast <Gtk::Widget&>(const_cast <const ALabel*>(this )->child ());
236
238
}
237
239
238
- Gtk::SizeRequestMode ALabel::get_request_mode_vfunc () const { return child ().get_request_mode (); }
240
+ // Test if the angle is vertical
241
+ static bool isVertical (uint angle) { return angle == 90 || angle == 270 ; }
242
+
243
+ Gtk::SizeRequestMode ALabel::get_request_mode_vfunc () const {
244
+ auto mode = child ().get_request_mode ();
245
+ if (isVertical (rotate_)) {
246
+ // we need to use the opposite mode from the child
247
+ switch (mode) {
248
+ case Gtk::SizeRequestMode::HEIGHT_FOR_WIDTH:
249
+ return Gtk::SizeRequestMode::WIDTH_FOR_HEIGHT;
250
+ case Gtk::SizeRequestMode::WIDTH_FOR_HEIGHT:
251
+ return Gtk::SizeRequestMode::HEIGHT_FOR_WIDTH;
252
+ default :
253
+ return mode;
254
+ }
255
+ } else {
256
+ return mode;
257
+ }
258
+ }
239
259
240
260
void ALabel::measure_vfunc (Gtk::Orientation orientation, int for_size, int & minimum, int & natural,
241
261
int & minimum_baseline, int & natural_baseline) const {
242
- return child ().measure (orientation, for_size, minimum, natural, minimum_baseline,
243
- natural_baseline);
262
+ bool vertical = isVertical (rotate_);
263
+ if (vertical) {
264
+ // the rotation is perpindicular, so we need to reverse the orientation.
265
+ if (orientation == Gtk::Orientation::HORIZONTAL) {
266
+ orientation = Gtk::Orientation::VERTICAL;
267
+ } else {
268
+ orientation = Gtk::Orientation::HORIZONTAL;
269
+ }
270
+ }
271
+ child ().measure (orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
272
+ if (vertical) {
273
+ // If we are rotated, the baseline doesn't make sense
274
+ minimum_baseline = -1 ;
275
+ natural_baseline = -1 ;
276
+ }
244
277
}
245
278
void ALabel::size_allocate_vfunc (int width, int height, int baseline) {
246
- Gtk::Allocation allocation;
247
- allocation.set_x (0 );
248
- allocation.set_y (0 );
249
- allocation.set_width (width);
250
- allocation.set_height (height);
279
+ // I can't find a C++ wrapper for Gsk
280
+ GskTransform* transform = nullptr ;
281
+ if (rotate_ != 0 ) {
282
+ // In order to rotate about the center, we need to translate to the center of the
283
+ // allocation, rotate, then translate back
284
+ float centerx = static_cast <float >(width) / 2 .0f ;
285
+ float centery = static_cast <float >(height) / 2 .0f ;
286
+ Gdk::Graphene::Point point{centerx, centery};
287
+ transform = gsk_transform_translate (nullptr , point.gobj ());
288
+ transform = gsk_transform_rotate (transform, rotate_);
289
+ if (isVertical (rotate_)) {
290
+ point.set_y (-centery);
291
+ point.set_x (-centerx);
292
+ } else {
293
+ point.set_x (-centerx);
294
+ point.set_y (-centery);
295
+ }
296
+ transform = gsk_transform_translate (transform, point.gobj ());
297
+ }
298
+
299
+ // For some reason there isn't a gtkmm equivalent of this
300
+ gtk_widget_allocate (GTK_WIDGET (child ().gobj ()), width, height, baseline, transform);
251
301
252
- child ().size_allocate (allocation, baseline);
253
302
if (menu_) {
254
303
// We need to present the menu as part of this function
255
304
menu_->present ();
0 commit comments