1 /* TUI layout window management. 2 3 Copyright (C) 1998-2023 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. When 59 PRESERVE_CMD_WIN_SIZE_P is true the current size of the TUI_CMD_WIN 60 is preserved, otherwise, the TUI_CMD_WIN will resize just like any 61 other window. */ 62 virtual void apply (int x, int y, int width, int height, 63 bool preserve_cmd_win_size_p) = 0; 64 65 /* Return the minimum and maximum height or width of this layout. 66 HEIGHT is true to fetch height, false to fetch width. */ 67 virtual void get_sizes (bool height, int *min_value, int *max_value) = 0; 68 69 /* True if the topmost (for vertical layouts), or the leftmost (for 70 horizontal layouts) item in this layout is boxed. */ 71 virtual bool first_edge_has_border_p () const = 0; 72 73 /* True if the bottommost (for vertical layouts), or the rightmost (for 74 horizontal layouts) item in this layout is boxed. */ 75 virtual bool last_edge_has_border_p () const = 0; 76 77 /* Return the name of this layout's window, or nullptr if this 78 layout does not represent a single window. */ 79 virtual const char *get_name () const 80 { 81 return nullptr; 82 } 83 84 /* Set the height of the window named NAME to NEW_HEIGHT, updating 85 the sizes of the other windows around it. */ 86 virtual tui_adjust_result set_height (const char *name, int new_height) = 0; 87 88 /* Set the width of the window named NAME to NEW_WIDTH, updating 89 the sizes of the other windows around it. */ 90 virtual tui_adjust_result set_width (const char *name, int new_width) = 0; 91 92 /* Remove some windows from the layout, leaving the command window 93 and the window being passed in here. */ 94 virtual void remove_windows (const char *name) = 0; 95 96 /* Replace the window named NAME in the layout with the window named 97 NEW_WINDOW. */ 98 virtual void replace_window (const char *name, const char *new_window) = 0; 99 100 /* Append the specification to this window to OUTPUT. DEPTH is the 101 depth of this layout in the hierarchy (zero-based). */ 102 virtual void specification (ui_file *output, int depth) = 0; 103 104 /* Return a FINGERPRINT string containing an abstract representation of 105 the location of the cmd window in this layout. 106 107 When called on a complete, top-level layout, the fingerprint will be a 108 non-empty string made of 'V' and 'H' characters, followed by a single 109 'C' character. Each 'V' and 'H' represents a vertical or horizontal 110 layout that must be passed through in order to find the cmd 111 window. 112 113 Of course, layouts are built recursively, so, when called on a partial 114 layout, if this object represents a single window, then either the 115 empty string is returned (for non-cmd windows), or a string 116 containing a single 'C' is returned. 117 118 For object representing layouts, if the layout contains the cmd 119 window then we will get back a valid fingerprint string (contains 'V' 120 and 'H', ends with 'C'), or, if this layout doesn't contain the cmd 121 window, an empty string is returned. */ 122 virtual std::string layout_fingerprint () const = 0; 123 124 /* Add all windows to the WINDOWS vector. */ 125 virtual void get_windows (std::vector<tui_win_info *> *windows) = 0; 126 127 /* The most recent space allocation. */ 128 int x = 0; 129 int y = 0; 130 int width = 0; 131 int height = 0; 132 133 protected: 134 135 tui_layout_base () = default; 136 }; 137 138 /* A TUI layout object that displays a single window. The window is 139 given by name. */ 140 class tui_layout_window : public tui_layout_base 141 { 142 public: 143 144 explicit tui_layout_window (const char *name) 145 : m_contents (name) 146 { 147 } 148 149 DISABLE_COPY_AND_ASSIGN (tui_layout_window); 150 151 std::unique_ptr<tui_layout_base> clone () const override; 152 153 void apply (int x, int y, int width, int height, 154 bool preserve_cmd_win_size_p) override; 155 156 const char *get_name () const override 157 { 158 return m_contents.c_str (); 159 } 160 161 tui_adjust_result set_height (const char *name, int new_height) override 162 { 163 return m_contents == name ? FOUND : NOT_FOUND; 164 } 165 166 tui_adjust_result set_width (const char *name, int new_width) override 167 { 168 return m_contents == name ? FOUND : NOT_FOUND; 169 } 170 171 bool first_edge_has_border_p () const override; 172 173 bool last_edge_has_border_p () const override; 174 175 void remove_windows (const char *name) override 176 { 177 } 178 179 void replace_window (const char *name, const char *new_window) override; 180 181 void specification (ui_file *output, int depth) override; 182 183 std::string layout_fingerprint () const override; 184 185 /* See tui_layout_base::get_windows. */ 186 void get_windows (std::vector<tui_win_info *> *windows) override 187 { 188 windows->push_back (m_window); 189 } 190 191 protected: 192 193 void get_sizes (bool height, int *min_value, int *max_value) override; 194 195 private: 196 197 /* Type of content to display. */ 198 std::string m_contents; 199 200 /* When a layout is applied, this is updated to point to the window 201 object. */ 202 tui_win_info *m_window = nullptr; 203 }; 204 205 /* A TUI layout that holds other layouts. */ 206 class tui_layout_split : public tui_layout_base 207 { 208 public: 209 210 /* Create a new layout. If VERTICAL is true, then windows in this 211 layout will be arranged vertically. */ 212 explicit tui_layout_split (bool vertical = true) 213 : m_vertical (vertical) 214 { 215 } 216 217 DISABLE_COPY_AND_ASSIGN (tui_layout_split); 218 219 /* Add a new split layout to this layout. WEIGHT is the desired 220 size, which is relative to the other weights given in this 221 layout. */ 222 void add_split (std::unique_ptr<tui_layout_split> &&layout, int weight); 223 224 /* Add a new window to this layout. NAME is the name of the window 225 to add. WEIGHT is the desired size, which is relative to the 226 other weights given in this layout. */ 227 void add_window (const char *name, int weight); 228 229 std::unique_ptr<tui_layout_base> clone () const override; 230 231 void apply (int x, int y, int width, int height, 232 bool preserve_cmd_win_size_p) override; 233 234 tui_adjust_result set_height (const char *name, int new_height) override 235 { 236 /* Pass false as the final argument to indicate change of height. */ 237 return set_size (name, new_height, false); 238 } 239 240 tui_adjust_result set_width (const char *name, int new_width) override 241 { 242 /* Pass true as the final argument to indicate change of width. */ 243 return set_size (name, new_width, true); 244 } 245 246 bool first_edge_has_border_p () const override; 247 248 bool last_edge_has_border_p () const override; 249 250 void remove_windows (const char *name) override; 251 252 void replace_window (const char *name, const char *new_window) override; 253 254 void specification (ui_file *output, int depth) override; 255 256 std::string layout_fingerprint () const override; 257 258 /* See tui_layout_base::get_windows. */ 259 void get_windows (std::vector<tui_win_info *> *windows) override 260 { 261 for (auto &item : m_splits) 262 item.layout->get_windows (windows); 263 } 264 265 protected: 266 267 void get_sizes (bool height, int *min_value, int *max_value) override; 268 269 private: 270 271 /* Used to implement set_height and set_width member functions. When 272 SET_WIDTH_P is true, set the width, otherwise, set the height of the 273 window named NAME to NEW_SIZE, updating the sizes of the other windows 274 around it as needed. The result indicates if the window NAME was 275 found and had its size adjusted, was found but was not adjusted, or 276 was not found at all. */ 277 tui_adjust_result set_size (const char *name, int new_size, 278 bool set_width_p); 279 280 /* Set the weights from the current heights (when m_vertical is true) or 281 widths (when m_vertical is false). */ 282 void set_weights_from_sizes (); 283 284 /* Structure used when resizing, or applying a layout. An instance of 285 this structure is created for each sub-layout. */ 286 struct size_info 287 { 288 /* The calculated size for this sub-layout. */ 289 int size; 290 291 /* The minimum and maximum sizes for this sub-layout, obtained by 292 calling the get_sizes member function. */ 293 int min_size; 294 int max_size; 295 296 /* True if this window will share a box border with the previous 297 window in the list. */ 298 bool share_box; 299 }; 300 301 /* Used for debug, prints the contents of INFO using tui_debug_printf. 302 Only call this when the global debug_tui is true. */ 303 static void tui_debug_print_size_info (const std::vector<size_info> &info); 304 305 /* Used for debug, returns a string describing the current weight of each 306 sub-layout. */ 307 std::string tui_debug_weights_to_string () const; 308 309 struct split 310 { 311 /* The requested weight. */ 312 int weight; 313 /* The layout. */ 314 std::unique_ptr<tui_layout_base> layout; 315 }; 316 317 /* The splits. */ 318 std::vector<split> m_splits; 319 320 /* True if the windows in this split are arranged vertically. */ 321 bool m_vertical; 322 }; 323 324 /* Add the specified window to the layout in a logical way. This 325 means setting up the most logical layout given the window to be 326 added. Only the source or disassembly window can be added this 327 way. */ 328 extern void tui_add_win_to_layout (enum tui_win_type); 329 330 /* Set the initial layout. */ 331 extern void tui_set_initial_layout (); 332 333 /* Switch to the next layout. */ 334 extern void tui_next_layout (); 335 336 /* Show the register window. Like "layout regs". */ 337 extern void tui_regs_layout (); 338 339 /* Remove some windows from the layout, leaving only the focused 340 window and the command window; if no window has the focus, then 341 some other window is chosen to remain. */ 342 extern void tui_remove_some_windows (); 343 344 /* Apply the current layout. When PRESERVE_CMD_WIN_SIZE_P is true the 345 current size of the TUI_CMD_WIN is preserved, otherwise, the TUI_CMD_WIN 346 will resize just like any other window. */ 347 extern void tui_apply_current_layout (bool); 348 349 /* Adjust the window height of WIN to NEW_HEIGHT. */ 350 extern void tui_adjust_window_height (struct tui_win_info *win, 351 int new_height); 352 353 /* Adjust the window width of WIN to NEW_WIDTH. */ 354 extern void tui_adjust_window_width (struct tui_win_info *win, 355 int new_width); 356 357 /* The type of a function that is used to create a TUI window. */ 358 359 typedef std::function<tui_win_info * (const char *name)> window_factory; 360 361 /* Register a new TUI window type. NAME is the name of the window 362 type. FACTORY is a function that can be called to instantiate the 363 window. */ 364 365 extern void tui_register_window (const char *name, window_factory &&factory); 366 367 #endif /* TUI_TUI_LAYOUT_H */ 368