gdb/tui: add new 'tui window width' command and 'winwidth' alias
[binutils-gdb.git] / gdb / tui / tui-layout.h
1 /* TUI layout window management.
2
3 Copyright (C) 1998-2022 Free Software Foundation, Inc.
4
5 Contributed by Hewlett-Packard Company.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #ifndef TUI_TUI_LAYOUT_H
23 #define TUI_TUI_LAYOUT_H
24
25 #include "ui-file.h"
26
27 #include "tui/tui.h"
28 #include "tui/tui-data.h"
29
30 /* Values that can be returned when handling a request to adjust a
31 window's size. */
32 enum tui_adjust_result
33 {
34 /* Requested window was not found here. */
35 NOT_FOUND,
36 /* Window was found but not handled. */
37 FOUND,
38 /* Window was found and handled. */
39 HANDLED
40 };
41
42 /* The basic object in a TUI layout. This represents a single piece
43 of screen real estate. Subclasses determine the exact
44 behavior. */
45 class tui_layout_base
46 {
47 public:
48
49 DISABLE_COPY_AND_ASSIGN (tui_layout_base);
50
51 virtual ~tui_layout_base () = default;
52
53 /* Clone this object. Ordinarily a layout is cloned before it is
54 used, so that any necessary modifications do not affect the
55 "skeleton" layout. */
56 virtual std::unique_ptr<tui_layout_base> clone () const = 0;
57
58 /* Change the size and location of this layout. */
59 virtual void apply (int x, int y, int width, int height) = 0;
60
61 /* Return the minimum and maximum height or width of this layout.
62 HEIGHT is true to fetch height, false to fetch width. */
63 virtual void get_sizes (bool height, int *min_value, int *max_value) = 0;
64
65 /* True if the topmost item in this layout is boxed. */
66 virtual bool top_boxed_p () const = 0;
67
68 /* True if the bottommost item in this layout is boxed. */
69 virtual bool bottom_boxed_p () const = 0;
70
71 /* Return the name of this layout's window, or nullptr if this
72 layout does not represent a single window. */
73 virtual const char *get_name () const
74 {
75 return nullptr;
76 }
77
78 /* Set the height of the window named NAME to NEW_HEIGHT, updating
79 the sizes of the other windows around it. */
80 virtual tui_adjust_result set_height (const char *name, int new_height) = 0;
81
82 /* Set the width of the window named NAME to NEW_WIDTH, updating
83 the sizes of the other windows around it. */
84 virtual tui_adjust_result set_width (const char *name, int new_width) = 0;
85
86 /* Remove some windows from the layout, leaving the command window
87 and the window being passed in here. */
88 virtual void remove_windows (const char *name) = 0;
89
90 /* Replace the window named NAME in the layout with the window named
91 NEW_WINDOW. */
92 virtual void replace_window (const char *name, const char *new_window) = 0;
93
94 /* Append the specification to this window to OUTPUT. DEPTH is the
95 depth of this layout in the hierarchy (zero-based). */
96 virtual void specification (ui_file *output, int depth) = 0;
97
98 /* Add all windows to the WINDOWS vector. */
99 virtual void get_windows (std::vector<tui_win_info *> *windows) = 0;
100
101 /* The most recent space allocation. */
102 int x = 0;
103 int y = 0;
104 int width = 0;
105 int height = 0;
106
107 protected:
108
109 tui_layout_base () = default;
110 };
111
112 /* A TUI layout object that displays a single window. The window is
113 given by name. */
114 class tui_layout_window : public tui_layout_base
115 {
116 public:
117
118 explicit tui_layout_window (const char *name)
119 : m_contents (name)
120 {
121 }
122
123 DISABLE_COPY_AND_ASSIGN (tui_layout_window);
124
125 std::unique_ptr<tui_layout_base> clone () const override;
126
127 void apply (int x, int y, int width, int height) override;
128
129 const char *get_name () const override
130 {
131 return m_contents.c_str ();
132 }
133
134 tui_adjust_result set_height (const char *name, int new_height) override
135 {
136 return m_contents == name ? FOUND : NOT_FOUND;
137 }
138
139 tui_adjust_result set_width (const char *name, int new_width) override
140 {
141 return m_contents == name ? FOUND : NOT_FOUND;
142 }
143
144 bool top_boxed_p () const override;
145
146 bool bottom_boxed_p () const override;
147
148 void remove_windows (const char *name) override
149 {
150 }
151
152 void replace_window (const char *name, const char *new_window) override;
153
154 void specification (ui_file *output, int depth) override;
155
156 /* See tui_layout_base::get_windows. */
157 void get_windows (std::vector<tui_win_info *> *windows) override
158 {
159 windows->push_back (m_window);
160 }
161
162 protected:
163
164 void get_sizes (bool height, int *min_value, int *max_value) override;
165
166 private:
167
168 /* Type of content to display. */
169 std::string m_contents;
170
171 /* When a layout is applied, this is updated to point to the window
172 object. */
173 tui_win_info *m_window = nullptr;
174 };
175
176 /* A TUI layout that holds other layouts. */
177 class tui_layout_split : public tui_layout_base
178 {
179 public:
180
181 /* Create a new layout. If VERTICAL is true, then windows in this
182 layout will be arranged vertically. */
183 explicit tui_layout_split (bool vertical = true)
184 : m_vertical (vertical)
185 {
186 }
187
188 DISABLE_COPY_AND_ASSIGN (tui_layout_split);
189
190 /* Add a new split layout to this layout. WEIGHT is the desired
191 size, which is relative to the other weights given in this
192 layout. */
193 void add_split (std::unique_ptr<tui_layout_split> &&layout, int weight);
194
195 /* Add a new window to this layout. NAME is the name of the window
196 to add. WEIGHT is the desired size, which is relative to the
197 other weights given in this layout. */
198 void add_window (const char *name, int weight);
199
200 std::unique_ptr<tui_layout_base> clone () const override;
201
202 void apply (int x, int y, int width, int height) override;
203
204 tui_adjust_result set_height (const char *name, int new_height) override
205 {
206 /* Pass false as the final argument to indicate change of height. */
207 return set_size (name, new_height, false);
208 }
209
210 tui_adjust_result set_width (const char *name, int new_width) override
211 {
212 /* Pass true as the final argument to indicate change of width. */
213 return set_size (name, new_width, true);
214 }
215
216 bool top_boxed_p () const override;
217
218 bool bottom_boxed_p () const override;
219
220 void remove_windows (const char *name) override;
221
222 void replace_window (const char *name, const char *new_window) override;
223
224 void specification (ui_file *output, int depth) override;
225
226 /* See tui_layout_base::get_windows. */
227 void get_windows (std::vector<tui_win_info *> *windows) override
228 {
229 for (auto &item : m_splits)
230 item.layout->get_windows (windows);
231 }
232
233 protected:
234
235 void get_sizes (bool height, int *min_value, int *max_value) override;
236
237 private:
238
239 /* Used to implement set_height and set_width member functions. When
240 SET_WIDTH_P is true, set the width, otherwise, set the height of the
241 window named NAME to NEW_SIZE, updating the sizes of the other windows
242 around it as needed. The result indicates if the window NAME was
243 found and had its size adjusted, was found but was not adjusted, or
244 was not found at all. */
245 tui_adjust_result set_size (const char *name, int new_size,
246 bool set_width_p);
247
248 /* Set the weights from the current heights (when m_vertical is true) or
249 widths (when m_vertical is false). */
250 void set_weights_from_sizes ();
251
252 struct split
253 {
254 /* The requested weight. */
255 int weight;
256 /* The layout. */
257 std::unique_ptr<tui_layout_base> layout;
258 };
259
260 /* The splits. */
261 std::vector<split> m_splits;
262
263 /* True if the windows in this split are arranged vertically. */
264 bool m_vertical;
265
266 /* True if this layout has already been applied at least once. */
267 bool m_applied = false;
268 };
269
270 /* Add the specified window to the layout in a logical way. This
271 means setting up the most logical layout given the window to be
272 added. Only the source or disassembly window can be added this
273 way. */
274 extern void tui_add_win_to_layout (enum tui_win_type);
275
276 /* Set the initial layout. */
277 extern void tui_set_initial_layout ();
278
279 /* Switch to the next layout. */
280 extern void tui_next_layout ();
281
282 /* Show the register window. Like "layout regs". */
283 extern void tui_regs_layout ();
284
285 /* Remove some windows from the layout, leaving only the focused
286 window and the command window; if no window has the focus, then
287 some other window is chosen to remain. */
288 extern void tui_remove_some_windows ();
289
290 /* Apply the current layout. */
291 extern void tui_apply_current_layout ();
292
293 /* Adjust the window height of WIN to NEW_HEIGHT. */
294 extern void tui_adjust_window_height (struct tui_win_info *win,
295 int new_height);
296
297 /* Adjust the window width of WIN to NEW_WIDTH. */
298 extern void tui_adjust_window_width (struct tui_win_info *win,
299 int new_width);
300
301 /* The type of a function that is used to create a TUI window. */
302
303 typedef std::function<tui_win_info * (const char *name)> window_factory;
304
305 /* Register a new TUI window type. NAME is the name of the window
306 type. FACTORY is a function that can be called to instantiate the
307 window. */
308
309 extern void tui_register_window (const char *name, window_factory &&factory);
310
311 #endif /* TUI_TUI_LAYOUT_H */