1 /*	Public domain	*/
2 
3 #ifndef _AGAR_WIDGET_TLIST_H_
4 #define _AGAR_WIDGET_TLIST_H_
5 
6 #include <agar/gui/scrollbar.h>
7 #include <agar/gui/menu.h>
8 #include <agar/gui/label.h>
9 
10 #include <agar/gui/begin.h>
11 
12 #define AG_TLIST_LABEL_MAX AG_LABEL_MAX
13 #define AG_TLIST_ARGS_MAX 8
14 
15 typedef struct ag_tlist_popup {
16 	const char *iclass;		/* Apply to items of this class */
17 	AG_Menu *menu;
18 	AG_MenuItem *item;
19 	AG_Window *panel;
20 	AG_TAILQ_ENTRY(ag_tlist_popup) popups;
21 } AG_TlistPopup;
22 
23 typedef struct ag_tlist_item {
24 	int selected;				/* Effective selection */
25 	AG_Surface *iconsrc;			/* Source icon (or NULL) */
26 	int icon;				/* Cached icon surface */
27 	void *p1;				/* User-supplied pointer */
28 	const char *cat;			/* User-supplied category */
29 	char text[AG_TLIST_LABEL_MAX];		/* Label text */
30 	int label;				/* Cached label surface */
31 	Uint depth;				/* Indent in tree display */
32 	Uint flags;
33 #define AG_TLIST_EXPANDED	  0x01	/* Child items visible (tree) */
34 #define AG_TLIST_HAS_CHILDREN	  0x02	/* Child items exist (tree) */
35 #define AG_TLIST_DYNICON	  0x04	/* Use a copy of iconsrc */
36 #define AG_TLIST_NO_SELECT	  0x08	/* Item is not selectable */
37 #define AG_TLIST_NO_POPUP	  0x10	/* Disable popups for item */
38 #define AG_TLIST_VISIBLE_CHILDREN AG_TLIST_EXPANDED
39 
40 	AG_TAILQ_ENTRY(ag_tlist_item) items;	/* Items in list */
41 	AG_TAILQ_ENTRY(ag_tlist_item) selitems;	/* Saved selection state */
42 } AG_TlistItem;
43 
44 typedef AG_TAILQ_HEAD(ag_tlist_itemq, ag_tlist_item) AG_TlistItemQ;
45 
46 typedef struct ag_tlist {
47 	struct ag_widget wid;
48 	Uint flags;
49 #define AG_TLIST_MULTI		0x001	/* Multiple selections (ctrl/shift) */
50 #define AG_TLIST_MULTITOGGLE	0x002	/* Multiple toggle-style selections */
51 #define AG_TLIST_POLL		0x004	/* Generate tlist-poll events */
52 #define AG_TLIST_TREE		0x010	/* Hack to display trees */
53 #define AG_TLIST_HFILL		0x020
54 #define AG_TLIST_VFILL		0x040
55 #define AG_TLIST_NOSELSTATE	0x100	/* Don't preserve sel state in poll */
56 #define AG_TLIST_SCROLLTOSEL	0x200	/* Scroll to initial selection */
57 #define AG_TLIST_REFRESH	0x400	/* Repopulate display (for polling) */
58 #define AG_TLIST_EXPAND		(AG_TLIST_HFILL|AG_TLIST_VFILL)
59 
60 	void *selected;			/* Default `selected' binding */
61 	int wHint, hHint;		/* Size hint */
62 	int wSpace;			/* Icon/text spacing */
63 
64 	int item_h;			/* Item height */
65 	int icon_w;			/* Item icon width */
66 	void *dblClicked;		/* Used by double click */
67 	AG_TlistItemQ items;		/* Current Items */
68 	AG_TlistItemQ selitems;		/* Saved item state */
69 	int nitems;			/* Current item count */
70 	int nvisitems;			/* Visible item count */
71 	AG_Scrollbar *sbar;		/* Vertical scrollbar */
72 	AG_TAILQ_HEAD_(ag_tlist_popup) popups; /* Popup menus */
73 	int (*compare_fn)(const AG_TlistItem *, const AG_TlistItem *);
74 	AG_Event *popupEv;		/* Popup menu hook */
75 	AG_Event *changedEv;		/* Selection change hook */
76 	AG_Event *dblClickEv;		/* Double click hook */
77 	AG_Timer moveTo;		/* Timer for keyboard motion */
78 	Uint32 wheelTicks;		/* For wheel acceleration */
79 	int wRow;			/* Row width */
80 	AG_Rect r;			/* View area */
81 	AG_Timer refreshTo;		/* Timer for polled mode updates */
82 	int rOffs;			/* Row display offset */
83 	AG_Timer dblClickTo;		/* Timer for detecting double clicks */
84 	int lastKeyDown;		/* For key repeat */
85 } AG_Tlist;
86 
87 #define AG_TLIST_FOREACH(it, tl) \
88 	AG_TAILQ_FOREACH(it, &(tl)->items, items)
89 
90 #define AG_TLIST_FOREACH_ITEM(p, tl, it, t)				\
91 	for((it) = AG_TAILQ_FIRST(&(tl)->items),			\
92 	     (p) = (it)!=NULL ? (struct t *)(it)->p1 : NULL;		\
93 	    (it) != AG_TAILQ_END(&(tl)->children) && (it)->p1 != NULL;	\
94 	    (it) = AG_TAILQ_NEXT((it), cobjs),				\
95 	     (p) = (it)!=NULL ? (struct t *)(it)->p1 : NULL)
96 
97 #define AG_TLIST_ITEM(n) AG_TlistSelectedItemPtr(AG_PTR(n))
98 
99 __BEGIN_DECLS
100 extern AG_WidgetClass agTlistClass;
101 
102 AG_Tlist *AG_TlistNew(void *, Uint);
103 AG_Tlist *AG_TlistNewPolled(void *, Uint, AG_EventFn, const char *, ...);
104 
105 void      AG_TlistSizeHint(AG_Tlist *, const char *, int);
106 void      AG_TlistSizeHintPixels(AG_Tlist *, int, int);
107 void      AG_TlistSizeHintLargest(AG_Tlist *, int);
108 #define   AG_TlistPrescale AG_TlistSizeHint
109 
110 void      AG_TlistSetItemHeight(AG_Tlist *, int);
111 void      AG_TlistSetIconWidth(AG_Tlist *, int);
112 void      AG_TlistSetIcon(AG_Tlist *, AG_TlistItem *, AG_Surface *);
113 void      AG_TlistSetRefresh(AG_Tlist *, int);
114 
115 void	       AG_TlistSetArgs(AG_TlistItem *, const char *, ...);
116 void	       AG_TlistDel(AG_Tlist *, AG_TlistItem *);
117 void           AG_TlistUniq(AG_Tlist *);
118 void	       AG_TlistClear(AG_Tlist *);
119 void	       AG_TlistRestore(AG_Tlist *);
120 AG_TlistItem  *AG_TlistAdd(AG_Tlist *, AG_Surface *, const char *, ...);
121 AG_TlistItem  *AG_TlistAddS(AG_Tlist *, AG_Surface *, const char *);
122 AG_TlistItem  *AG_TlistAddHead(AG_Tlist *, AG_Surface *, const char *, ...);
123 AG_TlistItem  *AG_TlistAddHeadS(AG_Tlist *, AG_Surface *, const char *);
124 AG_TlistItem  *AG_TlistAddPtr(AG_Tlist *, AG_Surface *, const char *, void *);
125 AG_TlistItem  *AG_TlistAddPtrHead(AG_Tlist *, AG_Surface *, const char *,
126 	                         void *);
127 void		 AG_TlistSelect(AG_Tlist *, AG_TlistItem *);
128 void		 AG_TlistDeselect(AG_Tlist *, AG_TlistItem *);
129 void		 AG_TlistSelectAll(AG_Tlist *);
130 AG_TlistItem	*AG_TlistSelectPtr(AG_Tlist *, void *);
131 AG_TlistItem	*AG_TlistSelectText(AG_Tlist *, const char *);
132 void		 AG_TlistDeselectAll(AG_Tlist *);
133 AG_TlistItem	*AG_TlistFindByIndex(AG_Tlist *, int);
134 AG_TlistItem	*AG_TlistSelectedItem(AG_Tlist *);
135 void		*AG_TlistSelectedItemPtr(AG_Tlist *);
136 void		*AG_TlistFindPtr(AG_Tlist *);
137 AG_TlistItem	*AG_TlistFindText(AG_Tlist *, const char *);
138 AG_TlistItem	*AG_TlistFirstItem(AG_Tlist *);
139 AG_TlistItem	*AG_TlistLastItem(AG_Tlist *);
140 AG_MenuItem	*AG_TlistSetPopup(AG_Tlist *, const char *);
141 void		 AG_TlistScrollToStart(AG_Tlist *);
142 void		 AG_TlistScrollToEnd(AG_Tlist *);
143 
144 void AG_TlistSetDblClickFn(AG_Tlist *, AG_EventFn, const char *, ...);
145 void AG_TlistSetPopupFn(AG_Tlist *, AG_EventFn, const char *, ...);
146 void AG_TlistSetChangedFn(AG_Tlist *, AG_EventFn, const char *, ...);
147 void AG_TlistSetCompareFn(AG_Tlist *, int (*)(const AG_TlistItem *,
148 		          const AG_TlistItem *));
149 int AG_TlistCompareStrings(const AG_TlistItem *, const AG_TlistItem *);
150 int AG_TlistComparePtrs(const AG_TlistItem *, const AG_TlistItem *);
151 int AG_TlistComparePtrsAndClasses(const AG_TlistItem *, const AG_TlistItem *);
152 int AG_TlistSort(AG_Tlist *);
153 
154 #define AG_TlistBegin AG_TlistClear
155 #define AG_TlistEnd AG_TlistRestore
156 
157 static __inline__ int
AG_TlistVisibleChildren(AG_Tlist * tl,AG_TlistItem * cit)158 AG_TlistVisibleChildren(AG_Tlist *tl, AG_TlistItem *cit)
159 {
160 	AG_TlistItem *sit;
161 
162 	AG_TAILQ_FOREACH(sit, &tl->selitems, selitems) {
163 		if (tl->compare_fn(sit, cit))
164 			break;
165 	}
166 	if (sit == NULL) {
167 		return (0);			/* TODO default setting */
168 	}
169 	return (sit->flags & AG_TLIST_VISIBLE_CHILDREN);
170 }
171 
172 static __inline__ void
AG_TlistRefresh(AG_Tlist * tl)173 AG_TlistRefresh(AG_Tlist *tl)
174 {
175 	AG_ObjectLock(tl);
176 	tl->flags |= AG_TLIST_REFRESH;
177 	AG_ObjectUnlock(tl);
178 }
179 __END_DECLS
180 
181 #include <agar/gui/close.h>
182 #endif /* _AGAR_WIDGET_TLIST_H_ */
183