gdk/geometry.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::Gravity;
4use glib::translate::*;
5use std::fmt;
6
7glib::wrapper! {
8 /// The [`Geometry`][crate::Geometry] struct gives the window manager information about
9 /// a window’s geometry constraints. Normally you would set these on
10 /// the GTK+ level using `gtk_window_set_geometry_hints()`. `GtkWindow`
11 /// then sets the hints on the [`Window`][crate::Window] it creates.
12 ///
13 /// [`Window::set_geometry_hints()`][crate::Window::set_geometry_hints()] expects the hints to be fully valid already
14 /// and simply passes them to the window manager; in contrast,
15 /// `gtk_window_set_geometry_hints()` performs some interpretation. For example,
16 /// `GtkWindow` will apply the hints to the geometry widget instead of the
17 /// toplevel window, if you set a geometry widget. Also, the
18 /// `min_width`/`min_height`/`max_width`/`max_height` fields may be set to -1, and
19 /// `GtkWindow` will substitute the size request of the window or geometry widget.
20 /// If the minimum size hint is not provided, `GtkWindow` will use its requisition
21 /// as the minimum size. If the minimum size is provided and a geometry widget is
22 /// set, `GtkWindow` will take the minimum size as the minimum size of the
23 /// geometry widget rather than the entire window. The base size is treated
24 /// similarly.
25 ///
26 /// The canonical use-case for `gtk_window_set_geometry_hints()` is to get a
27 /// terminal widget to resize properly. Here, the terminal text area should be
28 /// the geometry widget; `GtkWindow` will then automatically set the base size to
29 /// the size of other widgets in the terminal window, such as the menubar and
30 /// scrollbar. Then, the `width_inc` and `height_inc` fields should be set to the
31 /// size of one character in the terminal. Finally, the base size should be set
32 /// to the size of one character. The net effect is that the minimum size of the
33 /// terminal will have a 1x1 character terminal area, and only terminal sizes on
34 /// the “character grid” will be allowed.
35 ///
36 /// Here’s an example of how the terminal example would be implemented, assuming
37 /// a terminal area widget called “terminal” and a toplevel window “toplevel”:
38 ///
39 ///
40 ///
41 /// **⚠️ The following code is in C ⚠️**
42 ///
43 /// ```C
44 /// GdkGeometry hints;
45 ///
46 /// hints.base_width = terminal->char_width;
47 /// hints.base_height = terminal->char_height;
48 /// hints.min_width = terminal->char_width;
49 /// hints.min_height = terminal->char_height;
50 /// hints.width_inc = terminal->char_width;
51 /// hints.height_inc = terminal->char_height;
52 ///
53 /// gtk_window_set_geometry_hints (GTK_WINDOW (toplevel),
54 /// GTK_WIDGET (terminal),
55 /// &hints,
56 /// GDK_HINT_RESIZE_INC |
57 /// GDK_HINT_MIN_SIZE |
58 /// GDK_HINT_BASE_SIZE);
59 /// ```
60 ///
61 /// The other useful fields are the `min_aspect` and `max_aspect` fields; these
62 /// contain a width/height ratio as a floating point number. If a geometry widget
63 /// is set, the aspect applies to the geometry widget rather than the entire
64 /// window. The most common use of these hints is probably to set `min_aspect` and
65 /// `max_aspect` to the same value, thus forcing the window to keep a constant
66 /// aspect ratio.
67 #[doc(alias = "GdkGeometry")]
68 pub struct Geometry(BoxedInline<ffi::GdkGeometry>);
69}
70
71impl Geometry {
72 #[allow(clippy::too_many_arguments)]
73 pub fn new(
74 min_width: i32,
75 min_height: i32,
76 max_width: i32,
77 max_height: i32,
78 base_width: i32,
79 base_height: i32,
80 width_inc: i32,
81 height_inc: i32,
82 min_aspect: f64,
83 max_aspect: f64,
84 win_gravity: Gravity,
85 ) -> Self {
86 assert_initialized_main_thread!();
87 unsafe {
88 Geometry::unsafe_from(ffi::GdkGeometry {
89 min_width,
90 min_height,
91 max_width,
92 max_height,
93 base_width,
94 base_height,
95 width_inc,
96 height_inc,
97 min_aspect,
98 max_aspect,
99 win_gravity: win_gravity.into_glib(),
100 })
101 }
102 }
103
104 pub fn min_width(&self) -> i32 {
105 self.inner.min_width
106 }
107 pub fn min_height(&self) -> i32 {
108 self.inner.min_height
109 }
110 pub fn max_width(&self) -> i32 {
111 self.inner.max_width
112 }
113 pub fn max_height(&self) -> i32 {
114 self.inner.max_height
115 }
116 pub fn base_width(&self) -> i32 {
117 self.inner.base_width
118 }
119 pub fn base_height(&self) -> i32 {
120 self.inner.base_height
121 }
122 pub fn width_inc(&self) -> i32 {
123 self.inner.width_inc
124 }
125 pub fn height_inc(&self) -> i32 {
126 self.inner.height_inc
127 }
128 pub fn min_aspect(&self) -> f64 {
129 self.inner.min_aspect
130 }
131 pub fn max_aspect(&self) -> f64 {
132 self.inner.max_aspect
133 }
134 pub fn win_gravity(&self) -> Gravity {
135 unsafe { from_glib(self.inner.win_gravity) }
136 }
137}
138
139impl fmt::Debug for Geometry {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 f.debug_struct("Geometry")
142 .field("min_width", &self.min_width())
143 .field("min_height", &self.min_height())
144 .field("max_width", &self.max_width())
145 .field("max_height", &self.max_height())
146 .field("base_width", &self.base_width())
147 .field("base_height", &self.base_height())
148 .field("width_inc", &self.width_inc())
149 .field("height_inc", &self.height_inc())
150 .field("min_aspect", &self.min_aspect())
151 .field("max_aspect", &self.max_aspect())
152 .field("win_gravity", &self.win_gravity())
153 .finish()
154 }
155}