1 /* 2 * Copyright 2012 - 2013 Michael Drake <tlsa@netsurf-browser.org> 3 * 4 * This file is part of NetSurf, http://www.netsurf-browser.org/ 5 * 6 * NetSurf is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; version 2 of the License. 9 * 10 * NetSurf is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 /** 20 * \file 21 * Treeview handling interface. 22 */ 23 24 #ifndef _NETSURF_DESKTOP_TREEVIEW_H_ 25 #define _NETSURF_DESKTOP_TREEVIEW_H_ 26 27 #include <stdbool.h> 28 #include <stdint.h> 29 #include <libwapcaplet/libwapcaplet.h> 30 31 #include "netsurf/mouse.h" 32 33 struct redraw_context; 34 struct core_window; 35 struct core_window_callback_table; 36 37 typedef struct treeview treeview; 38 typedef struct treeview_node treeview_node; 39 40 41 /** 42 * treeview node type 43 */ 44 enum treeview_node_type { 45 TREE_NODE_NONE = 0, /**< No node */ 46 TREE_NODE_ROOT = (1 << 0), /**< Node is treeview's root */ 47 TREE_NODE_FOLDER = (1 << 1), /**< Node is folder */ 48 TREE_NODE_ENTRY = (1 << 2) /**< Node is an entry */ 49 }; 50 51 52 /** 53 * Relationship between nodes 54 */ 55 enum treeview_relationship { 56 TREE_REL_FIRST_CHILD, 57 TREE_REL_NEXT_SIBLING 58 }; 59 60 61 /** 62 * Node change handling options 63 */ 64 typedef enum { 65 TREE_OPTION_NONE = (0), /* No flags set */ 66 TREE_OPTION_SPECIAL_DIR = (1 << 0), /* Special folder */ 67 TREE_OPTION_SUPPRESS_RESIZE = (1 << 1), /* Suppress callback */ 68 TREE_OPTION_SUPPRESS_REDRAW = (1 << 2) /* Suppress callback */ 69 } treeview_node_options_flags; 70 71 /** 72 * treeview control flags 73 */ 74 typedef enum { 75 TREEVIEW_NO_FLAGS = (0), /**< No flags set */ 76 TREEVIEW_NO_MOVES = (1 << 0), /**< No node drags */ 77 TREEVIEW_NO_DELETES = (1 << 1), /**< No node deletes */ 78 TREEVIEW_READ_ONLY = TREEVIEW_NO_MOVES | TREEVIEW_NO_DELETES, 79 TREEVIEW_DEL_EMPTY_DIRS = (1 << 2), /**< Delete dirs on empty */ 80 TREEVIEW_SEARCHABLE = (1 << 3), /**< Treeview has search bar */ 81 } treeview_flags; 82 83 /** 84 * treeview message types 85 */ 86 enum treeview_msg { 87 TREE_MSG_NODE_DELETE, /**< Node to be deleted */ 88 TREE_MSG_NODE_EDIT, /**< Node to be edited */ 89 TREE_MSG_NODE_LAUNCH /**< Node to be launched */ 90 }; 91 92 93 /** 94 * treeview message 95 */ 96 struct treeview_node_msg { 97 enum treeview_msg msg; /**< The message type */ 98 union { 99 struct { 100 bool user; /**< True iff delete by user interaction */ 101 } delete; 102 struct { 103 lwc_string *field; /**< The field being edited */ 104 const char *text; /**< The proposed new value */ 105 } node_edit; /* Client may call treeview_update_node_* */ 106 struct { 107 browser_mouse_state mouse; /* Button / modifier used */ 108 } node_launch; 109 } data; /**< The message data. */ 110 }; 111 112 113 /** 114 * treeview field flags 115 */ 116 enum treeview_field_flags { 117 TREE_FLAG_NONE = 0, /**< No flags set */ 118 TREE_FLAG_ALLOW_EDIT = (1 << 0), /**< Whether allow edit field */ 119 TREE_FLAG_DEFAULT = (1 << 1), /**< Whether field is default */ 120 TREE_FLAG_SHOW_NAME = (1 << 2), /**< Whether field name shown */ 121 TREE_FLAG_COPY_TEXT = (1 << 3), /**< Whether to copy to clipb */ 122 TREE_FLAG_SEARCHABLE = (1 << 4), /**< Whether field is searchable */ 123 }; 124 125 126 /** 127 * Treeview field description 128 */ 129 struct treeview_field_desc { 130 lwc_string *field; /**< A treeview field name */ 131 enum treeview_field_flags flags; /**< Flags for field */ 132 }; 133 134 135 /** 136 * Treeview field data 137 */ 138 struct treeview_field_data { 139 lwc_string *field; /**< Field name */ 140 const char *value; /**< Field value */ 141 size_t value_len; /**< Field value length (bytes) */ 142 }; 143 144 145 /** 146 * Client callbacks for events concerning nodes 147 */ 148 struct treeview_callback_table { 149 nserror (*folder)(struct treeview_node_msg msg, void *data); 150 nserror (*entry)(struct treeview_node_msg msg, void *data); 151 }; 152 153 154 /** 155 * Prepare treeview module for treeview usage 156 * 157 * \return NSERROR_OK on success, appropriate error otherwise 158 */ 159 nserror treeview_init(void); 160 161 162 /** 163 * Finalise the treeview module (all treeviews must have been destroyed first) 164 * 165 * \return NSERROR_OK on success, appropriate error otherwise 166 */ 167 nserror treeview_fini(void); 168 169 170 /** 171 * Create a treeview 172 * 173 * The fields array order is as follows (N = n_fields): 174 * 175 * fields[0] Main field for entries (shown when not expanded) 176 * fields[1]...fields[N-2] Additional fields for entries 177 * fields[N-1] Field for folder nodes 178 * 179 * So fields[0] and fields[N-1] have TREE_FLAG_DEFAULT set. 180 * 181 * \param tree Returns created treeview object 182 * \param callbacks Treeview client node event callbacks 183 * \param n_fields Number of treeview fields (see description) 184 * \param fields Array of treeview fields 185 * \param cw_t Callback table for core_window containing the treeview 186 * \param cw The core_window in which the treeview is shown 187 * \param flags Treeview behaviour flags 188 * \return NSERROR_OK on success, appropriate error otherwise 189 */ 190 nserror treeview_create(treeview **tree, 191 const struct treeview_callback_table *callbacks, 192 int n_fields, struct treeview_field_desc fields[], 193 const struct core_window_callback_table *cw_t, 194 struct core_window *cw, treeview_flags flags); 195 196 197 /** 198 * Attach a treeview to a corewindow. 199 * 200 * Treeview must be detached. 201 * 202 * \param tree Treeview object 203 * \param cw_t Callback table for core_window containing the treeview 204 * \param cw The core_window in which the treeview is shown 205 * \return NSERROR_OK on success, appropriate error otherwise 206 */ 207 nserror treeview_cw_attach(treeview *tree, 208 const struct core_window_callback_table *cw_t, 209 struct core_window *cw); 210 211 212 /** 213 * Detach a treeview from a corewindow 214 * 215 * \param tree Treeview object 216 * \return NSERROR_OK on success, appropriate error otherwise 217 */ 218 nserror treeview_cw_detach(treeview *tree); 219 220 221 /** 222 * Destroy a treeview object 223 * 224 * Will emit folder and entry deletion msg callbacks for all nodes in treeview. 225 * 226 * \param tree Treeview object to destroy 227 * \return NSERROR_OK on success, appropriate error otherwise 228 */ 229 nserror treeview_destroy(treeview *tree); 230 231 232 /** 233 * Find a relation for node creation. 234 * 235 * If at_y is set, we find a relation that will put the created node at that 236 * position. 237 * 238 * If at_y is unset, we find a relation that would put the node below the first 239 * selected node, or at the end of the treeview if no nodes selected. 240 * 241 * \param tree Treeview object in which to create folder 242 * \param relation Existing node to insert as relation of, or NULL 243 * \param rel Folder's relationship to relation 244 * \param at_y Iff true, insert at y-offset 245 * \param y Y-offset in px from top of hotlist. Ignored if (!at_y). 246 * \return NSERROR_OK on success, appropriate error otherwise 247 */ 248 nserror treeview_get_relation(treeview *tree, treeview_node **relation, 249 enum treeview_relationship *rel, 250 bool at_y, int y); 251 252 253 /** 254 * Create a folder node in given treeview 255 * 256 * \param tree Treeview object in which to create folder 257 * \param folder Returns created folder node 258 * \param relation Existing node to insert as relation of, or NULL 259 * \param rel Folder's relationship to relation 260 * \param field Field data 261 * \param data Client data for node event callbacks 262 * \param flags Treeview node options flags 263 * \return NSERROR_OK on success, appropriate error otherwise 264 * 265 * Field name must match name past in treeview_create fields[N-1]. 266 * 267 * If relation is NULL, will insert as child of root node. 268 */ 269 nserror treeview_create_node_folder(treeview *tree, 270 treeview_node **folder, 271 treeview_node *relation, 272 enum treeview_relationship rel, 273 const struct treeview_field_data *field, 274 void *data, 275 treeview_node_options_flags flags); 276 277 278 /** 279 * Create an entry node in given treeview 280 * 281 * \param tree Treeview object in which to create entry 282 * \param entry Returns created entry node 283 * \param relation Existing node to insert as relation of, or NULL 284 * \param rel Folder's relationship to relation 285 * \param fields Array of field data 286 * \param data Client data for node event callbacks 287 * \param flags Treeview node options flags 288 * \return NSERROR_OK on success, appropriate error otherwise 289 * 290 * Fields array names must match names past in treeview_create fields[0...N-2]. 291 * 292 * If relation is NULL, will insert as child of root node. 293 */ 294 nserror treeview_create_node_entry(treeview *tree, 295 treeview_node **entry, 296 treeview_node *relation, 297 enum treeview_relationship rel, 298 const struct treeview_field_data fields[], 299 void *data, 300 treeview_node_options_flags flags); 301 302 303 /** 304 * Update an folder node in given treeview 305 * 306 * \param tree Treeview object in which to create entry 307 * \param folder Folder node to update 308 * \param field New field data 309 * \param data Client data for node event callbacks 310 * \return NSERROR_OK on success, appropriate error otherwise 311 * 312 * Field name must match name past in treeview_create fields[N-1]. 313 */ 314 nserror treeview_update_node_folder(treeview *tree, 315 treeview_node *folder, 316 const struct treeview_field_data *field, 317 void *data); 318 319 320 /** 321 * Update an entry node in given treeview 322 * 323 * \param tree Treeview object in which to create entry 324 * \param entry Entry node to update 325 * \param fields Array of new field data 326 * \param data Client data for node event callbacks 327 * \return NSERROR_OK on success, appropriate error otherwise 328 * 329 * Fields array names must match names past in treeview_create fields[0...N-2]. 330 */ 331 nserror treeview_update_node_entry(treeview *tree, 332 treeview_node *entry, 333 const struct treeview_field_data fields[], 334 void *data); 335 336 337 /** 338 * Client callback for treeview_walk 339 * 340 * \param ctx Client context 341 * \param node_data Client data for the current treeview node 342 * \param type The node type 343 * \param abort Set to true to abort treeview walk prematurely 344 * \return NSERROR_OK on success, or appropriate error otherwise 345 */ 346 typedef nserror (*treeview_walk_cb)(void *ctx, void *node_data, 347 enum treeview_node_type type, bool *abort); 348 349 350 /** 351 * Walk (depth first) a treeview subtree, calling a callback at each node of 352 * required type. 353 * 354 * Example usage: To export a treeview as XML, XML elements can be opened in 355 * enter_cb, and closed in leave_cb. 356 * 357 * Note, if deleting returned node in enter_cb, the walk must be terminated by 358 * setting abort to true. 359 * 360 * \param tree Treeview object to walk 361 * \param root Root node to walk tree from (or NULL for tree root) 362 * \param enter_cb Function to call on entering nodes, or NULL 363 * \param leave_cb Function to call on leaving nodes, or NULL 364 * \param ctx Client context, passed back to callback function 365 * \param type The node type(s) of interest 366 * \return NSERROR_OK on success, or appropriate error otherwise 367 */ 368 nserror treeview_walk(treeview *tree, treeview_node *root, 369 treeview_walk_cb enter_cb, treeview_walk_cb leave_cb, 370 void *ctx, enum treeview_node_type type); 371 372 373 /** 374 * Delete a treeview node 375 * 376 * \param tree Treeview object to delete node from 377 * \param n Node to delete 378 * \param flags Treeview node options flags 379 * \return NSERROR_OK on success, appropriate error otherwise 380 * 381 * Will emit folder or entry deletion msg callback. 382 */ 383 nserror treeview_delete_node(treeview *tree, treeview_node *n, 384 treeview_node_options_flags flags); 385 386 387 /** 388 * Expand a treeview node 389 * 390 * \param tree Treeview object to expand node in 391 * \param node Node to expand 392 * \return NSERROR_OK on success, appropriate error otherwise 393 */ 394 nserror treeview_node_expand(treeview *tree, treeview_node *node); 395 396 397 /** 398 * Contract a treeview node 399 * 400 * \param tree Treeview object to contract node in 401 * \param node Node to contract 402 * \return NSERROR_OK on success, appropriate error otherwise 403 */ 404 nserror treeview_node_contract(treeview *tree, treeview_node *node); 405 406 407 /** 408 * Expand a treeview's nodes 409 * 410 * \param tree Treeview object to expand nodes in 411 * \param only_folders Iff true, only folders are expanded. 412 * \return NSERROR_OK on success, appropriate error otherwise 413 */ 414 nserror treeview_expand(treeview *tree, bool only_folders); 415 416 417 /** 418 * Contract a treeview's nodes 419 * 420 * \param tree Treeview object to contract nodes in 421 * \param all Iff false, only entries are contracted. 422 * \return NSERROR_OK on success, appropriate error otherwise 423 */ 424 nserror treeview_contract(treeview *tree, bool all); 425 426 427 /** 428 * Redraw a treeview object 429 * 430 * \param tree Treeview object to render 431 * \param x X coordinate to render treeview at 432 * \param y Y coordinate to render treeview at 433 * \param clip Current clip rectangle (wrt tree origin) 434 * \param ctx Current redraw context 435 */ 436 void treeview_redraw(treeview *tree, int x, int y, struct rect *clip, 437 const struct redraw_context *ctx); 438 439 440 /** 441 * Key press handling for treeviews. 442 * 443 * \param tree The treeview which got the keypress 444 * \param key The ucs4 character codepoint 445 * \return true if the keypress is dealt with, false otherwise. 446 */ 447 bool treeview_keypress(treeview *tree, uint32_t key); 448 449 450 /** 451 * Handles all kinds of mouse action 452 * 453 * \param tree Treeview object 454 * \param mouse The current mouse state 455 * \param x X coordinate 456 * \param y Y coordinate 457 */ 458 void treeview_mouse_action(treeview *tree, 459 browser_mouse_state mouse, int x, int y); 460 461 462 /** 463 * Determine whether treeview has a selection 464 * 465 * \param tree Treeview object to delete node from 466 * \return true iff treeview has a selection 467 */ 468 bool treeview_has_selection(treeview *tree); 469 470 471 /** 472 * Get the first selected node 473 * 474 * \param tree Treeview object to get selected node in 475 * \param node_data Client data for the selected treeview node, or NULL 476 * \return node type of first selected node. 477 */ 478 enum treeview_node_type treeview_get_selection(treeview *tree, 479 void **node_data); 480 481 482 /** 483 * Edit the first selected node 484 * 485 * \param tree Treeview object to edit selected node in 486 */ 487 void treeview_edit_selection(treeview *tree); 488 489 490 /** 491 * Find current height of a treeview 492 * 493 * \param tree Treeview object to find height of 494 * \return height of treeview in px 495 */ 496 int treeview_get_height(treeview *tree); 497 498 499 /** 500 * Set the search string for a treeview with \ref TREEVIEW_SEARCHABLE 501 * 502 * \param tree Tree to set the search string for. 503 * \return NSERROR_OK on success, appropriate error otherwise 504 */ 505 nserror treeview_set_search_string( 506 treeview *tree, 507 const char *string); 508 509 #endif 510