1 1.1 christos /* TUI layout window management. 2 1.1 christos 3 1.1.1.11 christos Copyright (C) 1998-2024 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos Contributed by Hewlett-Packard Company. 6 1.1 christos 7 1.1 christos This file is part of GDB. 8 1.1 christos 9 1.1 christos This program is free software; you can redistribute it and/or modify 10 1.1 christos it under the terms of the GNU General Public License as published by 11 1.1 christos the Free Software Foundation; either version 3 of the License, or 12 1.1 christos (at your option) any later version. 13 1.1 christos 14 1.1 christos This program is distributed in the hope that it will be useful, 15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 1.1 christos GNU General Public License for more details. 18 1.1 christos 19 1.1 christos You should have received a copy of the GNU General Public License 20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 1.1 christos 22 1.1.1.12 christos #ifndef GDB_TUI_TUI_LAYOUT_H 23 1.1.1.12 christos #define GDB_TUI_TUI_LAYOUT_H 24 1.1 christos 25 1.1.1.9 christos #include "ui-file.h" 26 1.1.1.9 christos 27 1.1 christos #include "tui/tui.h" 28 1.1 christos #include "tui/tui-data.h" 29 1.1.1.11 christos #include "gdbsupport/iterator-range.h" 30 1.1.1.11 christos 31 1.1.1.11 christos #include <unordered_map> 32 1.1 christos 33 1.1.1.9 christos /* Values that can be returned when handling a request to adjust a 34 1.1.1.9 christos window's size. */ 35 1.1.1.9 christos enum tui_adjust_result 36 1.1.1.9 christos { 37 1.1.1.9 christos /* Requested window was not found here. */ 38 1.1.1.9 christos NOT_FOUND, 39 1.1.1.9 christos /* Window was found but not handled. */ 40 1.1.1.9 christos FOUND, 41 1.1.1.9 christos /* Window was found and handled. */ 42 1.1.1.9 christos HANDLED 43 1.1.1.9 christos }; 44 1.1.1.9 christos 45 1.1.1.9 christos /* The basic object in a TUI layout. This represents a single piece 46 1.1.1.9 christos of screen real estate. Subclasses determine the exact 47 1.1.1.9 christos behavior. */ 48 1.1.1.9 christos class tui_layout_base 49 1.1.1.9 christos { 50 1.1.1.9 christos public: 51 1.1.1.9 christos 52 1.1.1.9 christos DISABLE_COPY_AND_ASSIGN (tui_layout_base); 53 1.1.1.9 christos 54 1.1.1.9 christos virtual ~tui_layout_base () = default; 55 1.1.1.9 christos 56 1.1.1.9 christos /* Clone this object. Ordinarily a layout is cloned before it is 57 1.1.1.9 christos used, so that any necessary modifications do not affect the 58 1.1.1.9 christos "skeleton" layout. */ 59 1.1.1.9 christos virtual std::unique_ptr<tui_layout_base> clone () const = 0; 60 1.1.1.9 christos 61 1.1.1.10 christos /* Change the size and location of this layout. When 62 1.1.1.12 christos PRESERVE_CMD_WIN_SIZE_P is true the current size of the command window 63 1.1.1.12 christos is preserved, otherwise, the command window will resize just like any 64 1.1.1.10 christos other window. */ 65 1.1.1.10 christos virtual void apply (int x, int y, int width, int height, 66 1.1.1.10 christos bool preserve_cmd_win_size_p) = 0; 67 1.1.1.9 christos 68 1.1.1.9 christos /* Return the minimum and maximum height or width of this layout. 69 1.1.1.9 christos HEIGHT is true to fetch height, false to fetch width. */ 70 1.1.1.9 christos virtual void get_sizes (bool height, int *min_value, int *max_value) = 0; 71 1.1.1.9 christos 72 1.1.1.10 christos /* True if the topmost (for vertical layouts), or the leftmost (for 73 1.1.1.10 christos horizontal layouts) item in this layout is boxed. */ 74 1.1.1.10 christos virtual bool first_edge_has_border_p () const = 0; 75 1.1.1.10 christos 76 1.1.1.10 christos /* True if the bottommost (for vertical layouts), or the rightmost (for 77 1.1.1.10 christos horizontal layouts) item in this layout is boxed. */ 78 1.1.1.10 christos virtual bool last_edge_has_border_p () const = 0; 79 1.1.1.9 christos 80 1.1.1.9 christos /* Return the name of this layout's window, or nullptr if this 81 1.1.1.9 christos layout does not represent a single window. */ 82 1.1.1.9 christos virtual const char *get_name () const 83 1.1.1.9 christos { 84 1.1.1.9 christos return nullptr; 85 1.1.1.9 christos } 86 1.1.1.9 christos 87 1.1.1.10 christos /* Set the height of the window named NAME to NEW_HEIGHT, updating 88 1.1.1.10 christos the sizes of the other windows around it. */ 89 1.1.1.10 christos virtual tui_adjust_result set_height (const char *name, int new_height) = 0; 90 1.1.1.10 christos 91 1.1.1.10 christos /* Set the width of the window named NAME to NEW_WIDTH, updating 92 1.1.1.9 christos the sizes of the other windows around it. */ 93 1.1.1.10 christos virtual tui_adjust_result set_width (const char *name, int new_width) = 0; 94 1.1.1.9 christos 95 1.1.1.9 christos /* Remove some windows from the layout, leaving the command window 96 1.1.1.9 christos and the window being passed in here. */ 97 1.1.1.9 christos virtual void remove_windows (const char *name) = 0; 98 1.1.1.9 christos 99 1.1.1.9 christos /* Replace the window named NAME in the layout with the window named 100 1.1.1.9 christos NEW_WINDOW. */ 101 1.1.1.9 christos virtual void replace_window (const char *name, const char *new_window) = 0; 102 1.1.1.9 christos 103 1.1.1.9 christos /* Append the specification to this window to OUTPUT. DEPTH is the 104 1.1.1.9 christos depth of this layout in the hierarchy (zero-based). */ 105 1.1.1.9 christos virtual void specification (ui_file *output, int depth) = 0; 106 1.1.1.9 christos 107 1.1.1.10 christos /* Return a FINGERPRINT string containing an abstract representation of 108 1.1.1.10 christos the location of the cmd window in this layout. 109 1.1.1.10 christos 110 1.1.1.10 christos When called on a complete, top-level layout, the fingerprint will be a 111 1.1.1.10 christos non-empty string made of 'V' and 'H' characters, followed by a single 112 1.1.1.10 christos 'C' character. Each 'V' and 'H' represents a vertical or horizontal 113 1.1.1.10 christos layout that must be passed through in order to find the cmd 114 1.1.1.11 christos window. A vertical or horizontal layout of just one window does not add 115 1.1.1.11 christos a 'V' or 'H' character. 116 1.1.1.10 christos 117 1.1.1.10 christos Of course, layouts are built recursively, so, when called on a partial 118 1.1.1.10 christos layout, if this object represents a single window, then either the 119 1.1.1.10 christos empty string is returned (for non-cmd windows), or a string 120 1.1.1.10 christos containing a single 'C' is returned. 121 1.1.1.10 christos 122 1.1.1.10 christos For object representing layouts, if the layout contains the cmd 123 1.1.1.11 christos window then we will get back a valid fingerprint string (may contain 'V' 124 1.1.1.10 christos and 'H', ends with 'C'), or, if this layout doesn't contain the cmd 125 1.1.1.10 christos window, an empty string is returned. */ 126 1.1.1.10 christos virtual std::string layout_fingerprint () const = 0; 127 1.1.1.10 christos 128 1.1.1.10 christos /* Add all windows to the WINDOWS vector. */ 129 1.1.1.10 christos virtual void get_windows (std::vector<tui_win_info *> *windows) = 0; 130 1.1.1.10 christos 131 1.1.1.9 christos /* The most recent space allocation. */ 132 1.1.1.9 christos int x = 0; 133 1.1.1.9 christos int y = 0; 134 1.1.1.9 christos int width = 0; 135 1.1.1.9 christos int height = 0; 136 1.1.1.9 christos 137 1.1.1.9 christos protected: 138 1.1.1.9 christos 139 1.1.1.9 christos tui_layout_base () = default; 140 1.1.1.9 christos }; 141 1.1.1.9 christos 142 1.1.1.9 christos /* A TUI layout object that displays a single window. The window is 143 1.1.1.9 christos given by name. */ 144 1.1.1.9 christos class tui_layout_window : public tui_layout_base 145 1.1.1.9 christos { 146 1.1.1.9 christos public: 147 1.1.1.9 christos 148 1.1.1.9 christos explicit tui_layout_window (const char *name) 149 1.1.1.9 christos : m_contents (name) 150 1.1.1.9 christos { 151 1.1.1.9 christos } 152 1.1.1.9 christos 153 1.1.1.9 christos DISABLE_COPY_AND_ASSIGN (tui_layout_window); 154 1.1.1.9 christos 155 1.1.1.9 christos std::unique_ptr<tui_layout_base> clone () const override; 156 1.1.1.9 christos 157 1.1.1.10 christos void apply (int x, int y, int width, int height, 158 1.1.1.10 christos bool preserve_cmd_win_size_p) override; 159 1.1.1.9 christos 160 1.1.1.9 christos const char *get_name () const override 161 1.1.1.9 christos { 162 1.1.1.9 christos return m_contents.c_str (); 163 1.1.1.9 christos } 164 1.1.1.9 christos 165 1.1.1.10 christos tui_adjust_result set_height (const char *name, int new_height) override 166 1.1.1.9 christos { 167 1.1.1.9 christos return m_contents == name ? FOUND : NOT_FOUND; 168 1.1.1.9 christos } 169 1.1.1.9 christos 170 1.1.1.10 christos tui_adjust_result set_width (const char *name, int new_width) override 171 1.1.1.10 christos { 172 1.1.1.10 christos return m_contents == name ? FOUND : NOT_FOUND; 173 1.1.1.10 christos } 174 1.1.1.10 christos 175 1.1.1.10 christos bool first_edge_has_border_p () const override; 176 1.1.1.9 christos 177 1.1.1.10 christos bool last_edge_has_border_p () const override; 178 1.1.1.9 christos 179 1.1.1.9 christos void remove_windows (const char *name) override 180 1.1.1.9 christos { 181 1.1.1.9 christos } 182 1.1.1.9 christos 183 1.1.1.9 christos void replace_window (const char *name, const char *new_window) override; 184 1.1.1.9 christos 185 1.1.1.9 christos void specification (ui_file *output, int depth) override; 186 1.1.1.9 christos 187 1.1.1.10 christos std::string layout_fingerprint () const override; 188 1.1.1.10 christos 189 1.1.1.10 christos /* See tui_layout_base::get_windows. */ 190 1.1.1.10 christos void get_windows (std::vector<tui_win_info *> *windows) override 191 1.1.1.10 christos { 192 1.1.1.11 christos if (m_window != nullptr && m_window->is_visible ()) 193 1.1.1.11 christos { 194 1.1.1.11 christos /* Only get visible windows. */ 195 1.1.1.11 christos windows->push_back (m_window); 196 1.1.1.11 christos } 197 1.1.1.10 christos } 198 1.1.1.10 christos 199 1.1.1.9 christos protected: 200 1.1.1.9 christos 201 1.1.1.9 christos void get_sizes (bool height, int *min_value, int *max_value) override; 202 1.1.1.9 christos 203 1.1.1.9 christos private: 204 1.1.1.9 christos 205 1.1.1.9 christos /* Type of content to display. */ 206 1.1.1.9 christos std::string m_contents; 207 1.1.1.9 christos 208 1.1.1.9 christos /* When a layout is applied, this is updated to point to the window 209 1.1.1.9 christos object. */ 210 1.1.1.9 christos tui_win_info *m_window = nullptr; 211 1.1.1.9 christos }; 212 1.1.1.9 christos 213 1.1.1.9 christos /* A TUI layout that holds other layouts. */ 214 1.1.1.9 christos class tui_layout_split : public tui_layout_base 215 1.1.1.9 christos { 216 1.1.1.9 christos public: 217 1.1.1.9 christos 218 1.1.1.9 christos /* Create a new layout. If VERTICAL is true, then windows in this 219 1.1.1.9 christos layout will be arranged vertically. */ 220 1.1.1.9 christos explicit tui_layout_split (bool vertical = true) 221 1.1.1.9 christos : m_vertical (vertical) 222 1.1.1.9 christos { 223 1.1.1.9 christos } 224 1.1.1.9 christos 225 1.1.1.9 christos DISABLE_COPY_AND_ASSIGN (tui_layout_split); 226 1.1.1.9 christos 227 1.1.1.9 christos /* Add a new split layout to this layout. WEIGHT is the desired 228 1.1.1.9 christos size, which is relative to the other weights given in this 229 1.1.1.9 christos layout. */ 230 1.1.1.9 christos void add_split (std::unique_ptr<tui_layout_split> &&layout, int weight); 231 1.1.1.9 christos 232 1.1.1.9 christos /* Add a new window to this layout. NAME is the name of the window 233 1.1.1.9 christos to add. WEIGHT is the desired size, which is relative to the 234 1.1.1.9 christos other weights given in this layout. */ 235 1.1.1.9 christos void add_window (const char *name, int weight); 236 1.1.1.9 christos 237 1.1.1.9 christos std::unique_ptr<tui_layout_base> clone () const override; 238 1.1.1.9 christos 239 1.1.1.10 christos void apply (int x, int y, int width, int height, 240 1.1.1.10 christos bool preserve_cmd_win_size_p) override; 241 1.1.1.9 christos 242 1.1.1.10 christos tui_adjust_result set_height (const char *name, int new_height) override 243 1.1.1.10 christos { 244 1.1.1.10 christos /* Pass false as the final argument to indicate change of height. */ 245 1.1.1.10 christos return set_size (name, new_height, false); 246 1.1.1.10 christos } 247 1.1.1.10 christos 248 1.1.1.10 christos tui_adjust_result set_width (const char *name, int new_width) override 249 1.1.1.10 christos { 250 1.1.1.10 christos /* Pass true as the final argument to indicate change of width. */ 251 1.1.1.10 christos return set_size (name, new_width, true); 252 1.1.1.10 christos } 253 1.1.1.9 christos 254 1.1.1.10 christos bool first_edge_has_border_p () const override; 255 1.1.1.9 christos 256 1.1.1.10 christos bool last_edge_has_border_p () const override; 257 1.1.1.9 christos 258 1.1.1.9 christos void remove_windows (const char *name) override; 259 1.1.1.9 christos 260 1.1.1.9 christos void replace_window (const char *name, const char *new_window) override; 261 1.1.1.9 christos 262 1.1.1.9 christos void specification (ui_file *output, int depth) override; 263 1.1.1.9 christos 264 1.1.1.10 christos std::string layout_fingerprint () const override; 265 1.1.1.10 christos 266 1.1.1.10 christos /* See tui_layout_base::get_windows. */ 267 1.1.1.10 christos void get_windows (std::vector<tui_win_info *> *windows) override 268 1.1.1.10 christos { 269 1.1.1.10 christos for (auto &item : m_splits) 270 1.1.1.10 christos item.layout->get_windows (windows); 271 1.1.1.10 christos } 272 1.1.1.10 christos 273 1.1.1.9 christos protected: 274 1.1.1.9 christos 275 1.1.1.9 christos void get_sizes (bool height, int *min_value, int *max_value) override; 276 1.1.1.9 christos 277 1.1.1.9 christos private: 278 1.1.1.9 christos 279 1.1.1.10 christos /* Used to implement set_height and set_width member functions. When 280 1.1.1.10 christos SET_WIDTH_P is true, set the width, otherwise, set the height of the 281 1.1.1.10 christos window named NAME to NEW_SIZE, updating the sizes of the other windows 282 1.1.1.10 christos around it as needed. The result indicates if the window NAME was 283 1.1.1.10 christos found and had its size adjusted, was found but was not adjusted, or 284 1.1.1.10 christos was not found at all. */ 285 1.1.1.10 christos tui_adjust_result set_size (const char *name, int new_size, 286 1.1.1.10 christos bool set_width_p); 287 1.1.1.10 christos 288 1.1.1.10 christos /* Set the weights from the current heights (when m_vertical is true) or 289 1.1.1.10 christos widths (when m_vertical is false). */ 290 1.1.1.10 christos void set_weights_from_sizes (); 291 1.1.1.10 christos 292 1.1.1.10 christos /* Structure used when resizing, or applying a layout. An instance of 293 1.1.1.10 christos this structure is created for each sub-layout. */ 294 1.1.1.10 christos struct size_info 295 1.1.1.10 christos { 296 1.1.1.10 christos /* The calculated size for this sub-layout. */ 297 1.1.1.10 christos int size; 298 1.1.1.10 christos 299 1.1.1.10 christos /* The minimum and maximum sizes for this sub-layout, obtained by 300 1.1.1.10 christos calling the get_sizes member function. */ 301 1.1.1.10 christos int min_size; 302 1.1.1.10 christos int max_size; 303 1.1.1.10 christos 304 1.1.1.10 christos /* True if this window will share a box border with the previous 305 1.1.1.10 christos window in the list. */ 306 1.1.1.10 christos bool share_box; 307 1.1.1.10 christos }; 308 1.1.1.10 christos 309 1.1.1.10 christos /* Used for debug, prints the contents of INFO using tui_debug_printf. 310 1.1.1.10 christos Only call this when the global debug_tui is true. */ 311 1.1.1.10 christos static void tui_debug_print_size_info (const std::vector<size_info> &info); 312 1.1.1.10 christos 313 1.1.1.10 christos /* Used for debug, returns a string describing the current weight of each 314 1.1.1.10 christos sub-layout. */ 315 1.1.1.10 christos std::string tui_debug_weights_to_string () const; 316 1.1.1.9 christos 317 1.1.1.9 christos struct split 318 1.1.1.9 christos { 319 1.1.1.9 christos /* The requested weight. */ 320 1.1.1.9 christos int weight; 321 1.1.1.9 christos /* The layout. */ 322 1.1.1.9 christos std::unique_ptr<tui_layout_base> layout; 323 1.1.1.9 christos }; 324 1.1.1.9 christos 325 1.1.1.9 christos /* The splits. */ 326 1.1.1.9 christos std::vector<split> m_splits; 327 1.1.1.9 christos 328 1.1.1.9 christos /* True if the windows in this split are arranged vertically. */ 329 1.1.1.9 christos bool m_vertical; 330 1.1.1.9 christos }; 331 1.1.1.9 christos 332 1.1.1.9 christos /* Add the specified window to the layout in a logical way. This 333 1.1.1.9 christos means setting up the most logical layout given the window to be 334 1.1.1.9 christos added. Only the source or disassembly window can be added this 335 1.1.1.9 christos way. */ 336 1.1 christos extern void tui_add_win_to_layout (enum tui_win_type); 337 1.1.1.9 christos 338 1.1.1.9 christos /* Set the initial layout. */ 339 1.1.1.9 christos extern void tui_set_initial_layout (); 340 1.1.1.9 christos 341 1.1.1.9 christos /* Switch to the next layout. */ 342 1.1.1.9 christos extern void tui_next_layout (); 343 1.1.1.9 christos 344 1.1.1.9 christos /* Show the register window. Like "layout regs". */ 345 1.1.1.9 christos extern void tui_regs_layout (); 346 1.1.1.9 christos 347 1.1.1.9 christos /* Remove some windows from the layout, leaving only the focused 348 1.1.1.9 christos window and the command window; if no window has the focus, then 349 1.1.1.9 christos some other window is chosen to remain. */ 350 1.1.1.9 christos extern void tui_remove_some_windows (); 351 1.1.1.9 christos 352 1.1.1.10 christos /* Apply the current layout. When PRESERVE_CMD_WIN_SIZE_P is true the 353 1.1.1.12 christos current size of the command window is preserved, otherwise, the command 354 1.1.1.12 christos window will resize just like any other window. */ 355 1.1.1.10 christos extern void tui_apply_current_layout (bool); 356 1.1.1.9 christos 357 1.1.1.9 christos /* Adjust the window height of WIN to NEW_HEIGHT. */ 358 1.1.1.9 christos extern void tui_adjust_window_height (struct tui_win_info *win, 359 1.1.1.9 christos int new_height); 360 1.1.1.9 christos 361 1.1.1.10 christos /* Adjust the window width of WIN to NEW_WIDTH. */ 362 1.1.1.10 christos extern void tui_adjust_window_width (struct tui_win_info *win, 363 1.1.1.10 christos int new_width); 364 1.1.1.10 christos 365 1.1.1.9 christos /* The type of a function that is used to create a TUI window. */ 366 1.1.1.9 christos 367 1.1.1.9 christos typedef std::function<tui_win_info * (const char *name)> window_factory; 368 1.1.1.9 christos 369 1.1.1.11 christos /* The type for a data structure that maps a window name to that window's 370 1.1.1.11 christos factory function. */ 371 1.1.1.11 christos typedef std::unordered_map<std::string, window_factory> window_types_map; 372 1.1.1.11 christos 373 1.1.1.9 christos /* Register a new TUI window type. NAME is the name of the window 374 1.1.1.9 christos type. FACTORY is a function that can be called to instantiate the 375 1.1.1.9 christos window. */ 376 1.1.1.9 christos 377 1.1.1.9 christos extern void tui_register_window (const char *name, window_factory &&factory); 378 1.1 christos 379 1.1.1.11 christos /* An iterator class that exposes just the window names from the 380 1.1.1.11 christos known_window_types map in tui-layout.c. This is just a wrapper around 381 1.1.1.11 christos an iterator of the underlying known_window_types map, but this just 382 1.1.1.11 christos exposes the window names. */ 383 1.1.1.11 christos 384 1.1.1.11 christos struct known_window_names_iterator 385 1.1.1.11 christos { 386 1.1.1.11 christos using known_window_types_iterator = window_types_map::iterator; 387 1.1.1.11 christos 388 1.1.1.11 christos known_window_names_iterator (known_window_types_iterator &&iter) 389 1.1.1.11 christos : m_iter (std::move (iter)) 390 1.1.1.11 christos { /* Nothing. */ } 391 1.1.1.11 christos 392 1.1.1.11 christos known_window_names_iterator &operator++ () 393 1.1.1.11 christos { 394 1.1.1.11 christos ++m_iter; 395 1.1.1.11 christos return *this; 396 1.1.1.11 christos } 397 1.1.1.11 christos 398 1.1.1.11 christos const std::string &operator* () const 399 1.1.1.11 christos { return (*m_iter).first; } 400 1.1.1.11 christos 401 1.1.1.11 christos bool operator!= (const known_window_names_iterator &other) const 402 1.1.1.11 christos { return m_iter != other.m_iter; } 403 1.1.1.11 christos 404 1.1.1.11 christos private: 405 1.1.1.11 christos 406 1.1.1.11 christos /* The underlying iterator. */ 407 1.1.1.11 christos known_window_types_iterator m_iter; 408 1.1.1.11 christos }; 409 1.1.1.11 christos 410 1.1.1.11 christos /* A range adapter that makes it possible to iterate over the names of all 411 1.1.1.11 christos known tui windows. */ 412 1.1.1.11 christos 413 1.1.1.11 christos using known_window_names_range 414 1.1.1.11 christos = iterator_range<known_window_names_iterator>; 415 1.1.1.11 christos 416 1.1.1.11 christos /* Return a range that can be used to walk over the name of all known tui 417 1.1.1.11 christos windows in a range-for loop. */ 418 1.1.1.11 christos 419 1.1.1.11 christos extern known_window_names_range all_known_window_names (); 420 1.1.1.11 christos 421 1.1.1.12 christos #endif /* GDB_TUI_TUI_LAYOUT_H */ 422