summaryrefslogtreecommitdiff
path: root/desktop/treeview.h
blob: abe0e568dfd6120d4105bc4ecee43933f8d6bef6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
/*
 * Copyright 2012 - 2013 Michael Drake <tlsa@netsurf-browser.org>
 *
 * This file is part of NetSurf, http://www.netsurf-browser.org/
 *
 * NetSurf is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * NetSurf is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * \file
 * Treeview handling interface.
 */

#ifndef _NETSURF_DESKTOP_TREEVIEW_H_
#define _NETSURF_DESKTOP_TREEVIEW_H_

#include <stdbool.h>
#include <stdint.h>
#include <libwapcaplet/libwapcaplet.h>

#include "netsurf/mouse.h"

struct redraw_context;
struct core_window;
struct core_window_callback_table;

typedef struct treeview treeview;
typedef struct treeview_node treeview_node;

enum treeview_node_type {
	TREE_NODE_NONE		= 0,		/**< No node  */
	TREE_NODE_ROOT		= (1 << 0),	/**< Node is treeview's root */
	TREE_NODE_FOLDER	= (1 << 1),	/**< Node is folder */
	TREE_NODE_ENTRY		= (1 << 2)	/**< Node is an entry */
};

enum treeview_relationship {
	TREE_REL_FIRST_CHILD,
	TREE_REL_NEXT_SIBLING
};					/**< Relationship between nodes */

typedef enum {
	TREE_OPTION_NONE		= (0),		/* No flags set */
	TREE_OPTION_SPECIAL_DIR		= (1 << 0),	/* Special folder */
	TREE_OPTION_SUPPRESS_RESIZE	= (1 << 1),	/* Suppress callback */
	TREE_OPTION_SUPPRESS_REDRAW	= (1 << 2)	/* Suppress callback */
} treeview_node_options_flags;		/**< Node change handling options */

typedef enum {
	TREEVIEW_NO_FLAGS	= (0),		/**< No flags set */
	TREEVIEW_NO_MOVES	= (1 << 0),	/**< No node drags */
	TREEVIEW_NO_DELETES	= (1 << 1),	/**< No node deletes */
	TREEVIEW_READ_ONLY	= TREEVIEW_NO_MOVES | TREEVIEW_NO_DELETES,
	TREEVIEW_DEL_EMPTY_DIRS	= (1 << 2)	/**< Delete dirs on empty */
} treeview_flags;

enum treeview_msg {
	TREE_MSG_NODE_DELETE,		/**< Node to be deleted */
	TREE_MSG_NODE_EDIT,		/**< Node to be edited */
	TREE_MSG_NODE_LAUNCH		/**< Node to be launched */
};
struct treeview_node_msg {
	enum treeview_msg msg; /**< The message type */
	union {
		struct {
			bool user; /* True iff delete by user interaction */
		} delete;
		struct {
			lwc_string *field; /* The field being edited */
			const char *text;  /* The proposed new value */
		} node_edit; /* Client may call treeview_update_node_* */
		struct {
			browser_mouse_state mouse; /* Button / modifier used */
		} node_launch;
	} data; /**< The message data. */
};

enum treeview_field_flags {
	TREE_FLAG_NONE		= 0,		/**< No flags set */
	TREE_FLAG_ALLOW_EDIT	= (1 << 0),	/**< Whether allow edit field */
	TREE_FLAG_DEFAULT	= (1 << 1),	/**< Whether field is default */
	TREE_FLAG_SHOW_NAME	= (1 << 2),	/**< Whether field name shown */
	TREE_FLAG_COPY_TEXT	= (1 << 3)	/**< Whether to copy to clipb */
};
struct treeview_field_desc {
	lwc_string *field;			/**< A treeview field name */
	enum treeview_field_flags flags;	/**< Flags for field */
}; /**< Treeview field description */

struct treeview_field_data {
	lwc_string *field;		/**< Field name */
	const char *value;		/**< Field value */
	size_t value_len;		/**< Field value length (bytes) */
};


struct treeview_callback_table {
	nserror (*folder)(struct treeview_node_msg msg, void *data);
	nserror (*entry)(struct treeview_node_msg msg, void *data);
}; /**< Client callbacks for events concerning nodes */

/**
 * Prepare treeview module for treeview usage
 *
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror treeview_init(void);

/**
 * Finalise the treeview module (all treeviews must have been destroyed first)
 *
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror treeview_fini(void);

/**
 * Create a treeview
 *
 * \param tree		Returns created treeview object
 * \param callbacks	Treeview client node event callbacks
 * \param n_fields	Number of treeview fields (see description)
 * \param fields	Array of treeview fields
 * \param cw_t		Callback table for core_window containing the treeview
 * \param cw		The core_window in which the treeview is shown
 * \param flags		Treeview behaviour flags
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * The fields array order is as follows (N = n_fields):
 *
 *    fields[0]			Main field for entries (shown when not expanded)
 *    fields[1]...fields[N-2]	Additional fields for entries
 *    fields[N-1]		Field for folder nodes
 *
 * So fields[0] and fields[N-1] have TREE_FLAG_DEFAULT set.
 */
nserror treeview_create(treeview **tree,
		const struct treeview_callback_table *callbacks,
		int n_fields, struct treeview_field_desc fields[],
		const struct core_window_callback_table *cw_t,
		struct core_window *cw, treeview_flags flags);

/**
 * Destroy a treeview object
 *
 * \param tree		Treeview object to destroy
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * Will emit folder and entry deletion msg callbacks for all nodes in treeview.
 */
nserror treeview_destroy(treeview *tree);

/**
 * Find a releation for node creation.
 *
 * \param tree		Treeview object in which to create folder
 * \param relation	Existing node to insert as relation of, or NULL
 * \param rel		Folder's relationship to relation
 * \param at_y		Iff true, insert at y-offest
 * \param y		Y-offset in px from top of hotlist.  Ignored if (!at_y).
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * If at_y is set, we find a relation that will put the created node at that
 * position.
 *
 * If at_y is unset, we find a relation that would put the node below the first
 * selected node, or at the end of the treeview if no nodes selected.
 */
nserror treeview_get_relation(treeview *tree, treeview_node **relation,
		enum treeview_relationship *rel, bool at_y, int y);

/**
 * Create a folder node in given treeview
 *
 * \param tree		Treeview object in which to create folder
 * \param folder	Returns created folder node
 * \param relation	Existing node to insert as relation of, or NULL
 * \param rel		Folder's relationship to relation
 * \param field		Field data
 * \param data		Client data for node event callbacks
 * \param flags		Treeview node options flags
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * Field name must match name past in treeview_create fields[N-1].
 *
 * If relation is NULL, will insert as child of root node.
 */
nserror treeview_create_node_folder(treeview *tree,
		treeview_node **folder,
		treeview_node *relation,
		enum treeview_relationship rel,
		const struct treeview_field_data *field,
		void *data, treeview_node_options_flags flags);

/**
 * Create an entry node in given treeview
 *
 * \param tree		Treeview object in which to create entry
 * \param entry		Returns created entry node
 * \param relation	Existing node to insert as relation of, or NULL
 * \param rel		Folder's relationship to relation
 * \param fields	Array of field data
 * \param data		Client data for node event callbacks
 * \param flags		Treeview node options flags
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * Fields array names must match names past in treeview_create fields[0...N-2].
 *
 * If relation is NULL, will insert as child of root node.
 */
nserror treeview_create_node_entry(treeview *tree,
		treeview_node **entry,
		treeview_node *relation,
		enum treeview_relationship rel,
		const struct treeview_field_data fields[],
		void *data, treeview_node_options_flags flags);

/**
 * Update an folder node in given treeview
 *
 * \param tree	 Treeview object in which to create entry
 * \param folder Folder node to update
 * \param field	 New field data
 * \param data	 Client data for node event callbacks
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * Field name must match name past in treeview_create fields[N-1].
 */
nserror treeview_update_node_folder(treeview *tree,
		treeview_node *folder,
		const struct treeview_field_data *field,
		void *data);

/**
 * Update an entry node in given treeview
 *
 * \param tree		Treeview object in which to create entry
 * \param entry		Entry node to update
 * \param fields	Array of new field data
 * \param data		Client data for node event callbacks
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * Fields array names must match names past in treeview_create fields[0...N-2].
 */
nserror treeview_update_node_entry(treeview *tree,
		treeview_node *entry,
		const struct treeview_field_data fields[],
		void *data);


/**
 * Client callback for treeview_walk
 *
 * \param ctx		Client context
 * \param node_data	Client data for the current treeview node
 * \param type		The node type
 * \param abort		Set to true to abort treeview walk prematurely
 * \return NSERROR_OK on success, or appropriate error otherwise
 */
typedef nserror (*treeview_walk_cb)(void *ctx, void *node_data,
		enum treeview_node_type type, bool *abort);

/**
 * Walk (depth first) a treeview subtree, calling a callback at each node of
 * required type.
 *
 * \param tree		Treeview object to walk
 * \param root		Root node to walk tree from (or NULL for tree root)
 * \param enter_cb	Function to call on entering nodes, or NULL
 * \param leave_cb	Function to call on leaving nodes, or NULL
 * \param ctx		Client context, passed back to callback function
 * \param type		The node type(s) of interest
 * \return NSERROR_OK on success, or appropriate error otherwise
 *
 * Example usage: To export a treeview as XML, XML elements can be opened in
 * enter_cb, and closed in leave_cb.
 *
 * Note, if deleting returned node in enter_cb, the walk must be terminated by
 * setting abort to true.
 */
nserror treeview_walk(treeview *tree, treeview_node *root,
		treeview_walk_cb enter_cb, treeview_walk_cb leave_cb,
		void *ctx, enum treeview_node_type type);

/**
 * Delete a treeview node
 *
 * \param tree		Treeview object to delete node from
 * \param n		Node to delete
 * \param flags		Treeview node options flags
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * Will emit folder or entry deletion msg callback.
 */
nserror treeview_delete_node(treeview *tree, treeview_node *n,
		treeview_node_options_flags flags);

/**
 * Expand a treeview node
 *
 * \param tree		Treeview object to expand node in
 * \param node		Node to expand
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror treeview_node_expand(treeview *tree, treeview_node *node);

/**
 * Contract a treeview node
 *
 * \param tree		Treeview object to contract node in
 * \param node		Node to contract
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror treeview_node_contract(treeview *tree, treeview_node *node);

/**
 * Expand a treeview's nodes
 *
 * \param tree		Treeview object to expand nodes in
 * \param only_folders	Iff true, only folders are expanded.
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror treeview_expand(treeview *tree, bool only_folders);

/**
 * Contract a treeview's nodes
 *
 * \param tree		Treeview object to contract nodes in
 * \param all		Iff false, only entries are contracted.
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror treeview_contract(treeview *tree, bool all);

/**
 * Redraw a treeview object
 *
 * \param tree		Treeview object to render
 * \param x		X coordinate to render treeview at
 * \param y		Y coordinate to render treeview at
 * \param clip		Current clip rectangle (wrt tree origin)
 * \param ctx		Current redraw context
 */
void treeview_redraw(treeview *tree, int x, int y, struct rect *clip,
		const struct redraw_context *ctx);

/**
 * Key press handling for treeviews.
 *
 * \param tree		The treeview which got the keypress
 * \param key		The ucs4 character codepoint
 * \return true if the keypress is dealt with, false otherwise.
 */
bool treeview_keypress(treeview *tree, uint32_t key);

/**
 * Handles all kinds of mouse action
 *
 * \param tree		Treeview object
 * \param mouse		The current mouse state
 * \param x		X coordinate
 * \param y		Y coordinate
 */
void treeview_mouse_action(treeview *tree,
		browser_mouse_state mouse, int x, int y);

/**
 * Determine whether treeview has a selection
 *
 * \param tree		Treeview object to delete node from
 * \return true iff treeview has a selection
 */
bool treeview_has_selection(treeview *tree);

/**
 * Get the first selected node
 *
 * \param tree		Treeview object to get selected node in
 * \param node_data	Client data for the selected treeview node, or NULL
 * \return node type of first selected node.
 */
enum treeview_node_type treeview_get_selection(treeview *tree,
		void **node_data);

/**
 * Edit the first selected node
 *
 * \param tree		Treeview object to edit selected node in
 */
void treeview_edit_selection(treeview *tree);

/**
 * Find current height of a treeview
 *
 * \param tree		Treeview object to find height of
 * \return height of treeview in px
 */
int treeview_get_height(treeview *tree);

#endif