- Set a default PCM volume so that something can be heard when driver is
[AROS.git] / test / Zune / texticonlist.c
blobb4b8fb07dcd158935a10e238ecce8347cf0ba82a
1 /*
2 Copyright © 2002-2004, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <exec/types.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
13 #include <dos/dos.h>
14 #include <dos/datetime.h>
15 #include <intuition/gadgetclass.h>
16 #include <intuition/icclass.h>
17 #include <proto/exec.h>
18 #include <proto/dos.h>
19 #include <proto/intuition.h>
20 #include <proto/muimaster.h>
21 #include <proto/utility.h>
22 #include <proto/graphics.h>
23 #include <proto/cybergraphics.h>
24 #include <clib/alib_protos.h>
26 #include <aros/debug.h>
28 /* the following should go in a single include file which then only
29 ** constits of the public constants and members. Actually this is easiey
32 #include <libraries/mui.h>
34 #include "../../workbench/system/Wanderer/Classes/iconlist_attributes.h"
35 #include "../../workbench/system/Wanderer/Classes/iconlist.h"
37 struct Library *MUIMasterBase;
39 Object *app;
40 struct MUI_CustomClass *CL_TextIconList, *CL_TextIconListview;
42 /*================== TextIconList class =====================*/
44 #define NUM_COLUMNS 6
46 #define MIN_COLUMN_WIDTH 10
48 #define COLUMN_ALIGN_LEFT 0
49 #define COLUMN_ALIGN_CENTER 1
50 #define COLUMN_ALIGN_RIGHT 2
52 #define LINE_SPACING_TOP 2
53 #define LINE_SPACING_BOTTOM 2
54 #define LINE_EXTRAHEIGHT (LINE_SPACING_TOP + LINE_SPACING_BOTTOM)
56 #define LINE_SPACING_LEFT 1
57 #define LINE_SPACING_RIGHT 1
58 #define LINE_EXTRAWIDTH (LINE_SPACING_LEFT + LINE_SPACING_RIGHT)
60 #define ENTRY_SPACING_LEFT 1
61 #define ENTRY_SPACING_RIGHT 1
62 #define ENTRY_EXTRAWIDTH (ENTRY_SPACING_LEFT + ENTRY_SPACING_RIGHT)
64 #define HEADERLINE_SPACING_TOP 3
65 #define HEADERLINE_SPACING_BOTTOM 3
66 #define HEADERLINE_EXTRAHEIGHT (HEADERLINE_SPACING_TOP + HEADERLINE_SPACING_BOTTOM)
68 #define HEADERLINE_SPACING_LEFT 1
69 #define HEADERLINE_SPACING_RIGHT 1
70 #define HEADERLINE_EXTRAWIDTH (HEADERLINE_SPACING_LEFT + HEADERLINE_SPACING_RIGHT)
72 #define HEADERENTRY_SPACING_LEFT 4
73 #define HEADERENTRY_SPACING_RIGHT 4
74 #define HEADERENTRY_EXTRAWIDTH (HEADERENTRY_SPACING_LEFT + HEADERENTRY_SPACING_RIGHT)
76 #define AUTOSCROLL_MILLIS 20
78 struct TextIconEntry
80 struct MinNode node;
81 struct MinNode selection_node;
82 struct FileInfoBlock fib;
83 LONG field_width[NUM_COLUMNS];
84 UBYTE datebuf[LEN_DATSTRING];
85 UBYTE timebuf[LEN_DATSTRING];
86 UBYTE sizebuf[30];
87 UBYTE protbuf[8];
88 UBYTE selected;
89 UBYTE dirty;
92 struct MyColor
94 ULONG pixel;
95 ULONG rgbpixel;
96 UBYTE alloced;
99 #define COLOR_COLUMN_BACKGROUND 0
100 #define COLOR_COLUMN_BACKGROUND_SORTED 1
101 #define COLOR_COLUMN_BACKGROUND_LASSO 2
102 #define COLOR_COLUMN_BACKGROUND_LASSO_SORTED 3
104 #define COLOR_SELECTED_BACKGROUND 4
105 #define COLOR_SELECTED_BACKGROUND_SORTED 5
106 #define COLOR_SELECTED_BACKGROUND_LASSO 6
107 #define COLOR_SELECTED_BACKGROUND_LASSO_SORTED 7
109 #define NUM_COLORS 8
111 static const ULONG rgb_colors[NUM_COLORS] =
113 0xFFFFFF,
114 0xF0F0F0,
115 0xE4E7Ef,
116 0xDEE1E9,
117 0x0A246A,
118 0x0A246A,
119 0x324882,
120 0x324882
123 static const ULONG pen_colors[NUM_COLORS] =
125 MPEN_SHINE,
126 MPEN_SHINE,
127 MPEN_BACKGROUND,
128 MPEN_BACKGROUND,
129 MPEN_FILL,
130 MPEN_FILL,
131 MPEN_FILL,
132 MPEN_FILL
135 struct TextIconList_DATA
137 APTR pool;
138 LONG view_x, view_y;
139 LONG view_width, view_height;
140 LONG width, height, lineheight, headerheight;
141 LONG update;
142 LONG update_scrolldx;
143 LONG update_scrolldy;
144 LONG update_entry;
145 struct MinList entries_list;
146 struct MinList selection_list;
147 struct RastPort temprp;
148 struct Rectangle view_rect;
149 struct Rectangle header_rect;
150 struct Rectangle lasso_rect, old_lasso_rect;
151 struct Rectangle *update_rect1, *update_rect2;
152 struct MyColor colors[NUM_COLORS];
153 LONG num_entries;
154 LONG num_selected;
155 LONG active_entry;
156 LONG click_x, click_y, click_column;
157 LONG column_pos[NUM_COLUMNS];
158 LONG column_maxwidth[NUM_COLUMNS];
159 LONG column_width[NUM_COLUMNS];
160 BYTE column_visible[NUM_COLUMNS];
161 BYTE column_align[NUM_COLUMNS];
162 BYTE column_clickable[NUM_COLUMNS];
163 BYTE column_sortable[NUM_COLUMNS];
164 STRPTR column_title[NUM_COLUMNS];
165 BYTE sort_column;
166 BYTE sort_direction;
167 BYTE sort_dirs;
168 LONG inputstate;
169 BOOL show_header;
170 BOOL is_setup;
171 BOOL is_shown;
172 BOOL lasso_active;
173 BOOL lasso_paint;
174 BOOL truecolor;
176 struct MUI_EventHandlerNode ehn;
177 struct MUI_InputHandlerNode thn;
180 #define UPDATE_SCROLL 2
181 #define UPDATE_DIRTY_ENTRIES 3
182 #define UPDATE_ALL 4
183 #define UPDATE_HEADER 5
185 #define INPUTSTATE_NONE 0
186 #define INPUTSTATE_PAN 1
187 #define INPUTSTATE_COL_RESIZE 2
188 #define INPUTSTATE_COL_HEADER_CLICK 3
189 #define INPUTSTATE_LASSO 4
191 #define MUIB_TextIconList (MUIB_AROS | 0x00000700)
193 #define MUIA_TextIconList_Left (MUIB_TextIconList | 0x00000000)
194 #define MUIA_TextIconList_Top (MUIB_TextIconList | 0x00000001)
195 #define MUIA_TextIconList_Width (MUIB_TextIconList | 0x00000002)
196 #define MUIA_TextIconList_Height (MUIB_TextIconList | 0x00000003)
197 #define MUIA_TextIconList_VisWidth (MUIB_TextIconList | 0x00000004)
198 #define MUIA_TextIconList_VisHeight (MUIB_TextIconList | 0x00000005)
200 #define MUIM_TextIconList_Clear (MUIB_TextIconList | 0x00000000)
201 #define MUIM_TextIconList_Add (MUIB_TextIconList | 0x00000001)
202 #define MUIM_TextIconList_AutoScroll (MUIB_TextIconList | 0x00000002)
204 struct MUIP_TextIconList_Clear {STACKULONG MethodID;};
205 struct MUIP_TextIconList_Add {STACKULONG MethodID; struct FileInfoBlock *fib;};
207 #define TextIconListObject BOOPSIOBJMACRO_START(CL_TextIconList->mcc_Class)
210 #define INDEX_NAME 0
211 #define INDEX_SIZE 1
212 #define INDEX_PROTECTION 2
213 #define INDEX_DATE 3
214 #define INDEX_TIME 4
215 #define INDEX_COMMENT 5
217 #define SORT_DRAWERS_FIRST 0
218 #define SORT_DRAWERS_MIXED 1
219 #define SORT_DRAWERS_LAST 2
221 #define SORT_DIRECTION_UP 0
222 #define SORT_DIRECTION_DOWN 1
224 #define SORT_BY_NAME 0
225 #define SORT_BY_DATE 1
226 #define SORT_BY_SIZE 2
228 static STRPTR GetTextIconEntryText(struct TextIconList_DATA *data, struct TextIconEntry *entry,
229 LONG index)
231 STRPTR ret = 0;
233 switch(index)
235 case INDEX_NAME:
236 ret = entry->fib.fib_FileName;
237 break;
239 case INDEX_SIZE:
240 ret = entry->sizebuf;
241 break;
243 case INDEX_DATE:
244 ret = entry->datebuf;
245 break;
247 case INDEX_TIME:
248 ret = entry->timebuf;
249 break;
251 case INDEX_COMMENT:
252 ret = entry->fib.fib_Comment;
253 break;
255 case INDEX_PROTECTION:
256 ret = entry->protbuf;
257 break;
260 return ret;
263 static STRPTR GetTextIconHeaderText(struct TextIconList_DATA *data, LONG index)
265 STRPTR ret = 0;
267 ret = data->column_title[index];
268 if (ret) return ret;
270 switch(index)
272 case INDEX_NAME:
273 ret = "Name";
274 break;
276 case INDEX_SIZE:
277 ret = "Size";
278 break;
280 case INDEX_DATE:
281 ret = "Date";
282 break;
284 case INDEX_TIME:
285 ret = "Time";
286 break;
288 case INDEX_COMMENT:
289 ret = "Comment";
290 break;
292 case INDEX_PROTECTION:
293 ret = "Protection";
294 break;
297 return ret;
300 static void CalcWidth(struct TextIconList_DATA *data)
302 LONG i, width = LINE_EXTRAWIDTH;
304 for(i = 0; i < NUM_COLUMNS; i++)
306 if (data->column_visible[i])
308 width += data->column_width[i];
312 data->width = width;
315 static void CalcEntryDimension(struct TextIconList_DATA *data, struct TextIconEntry *entry)
317 LONG i;
318 STRPTR text;
319 LONG len;
321 for (i = 0; i < NUM_COLUMNS; i++)
323 text = GetTextIconEntryText(data, entry, i);
324 len = TextLength(&data->temprp, text, strlen(text));
326 entry->field_width[i] = len + ENTRY_EXTRAWIDTH;
328 if (entry->field_width[i] > data->column_maxwidth[i])
330 data->column_maxwidth[i] = entry->field_width[i];
336 static void CalcAllEntryDimensions(struct TextIconList_DATA *data)
338 struct TextIconEntry *entry;
340 ForeachNode(&data->entries_list, entry)
342 CalcEntryDimension(data, entry);
346 static void RecalcColumnMaxWidths(struct TextIconList_DATA *data)
348 struct TextIconEntry *entry;
349 LONG i;
351 for(i = 0; i < NUM_COLUMNS; i++)
353 data->column_maxwidth[i] = 0;
356 ForeachNode(&data->entries_list, entry)
358 for(i = 0; i < NUM_COLUMNS; i++)
360 if (entry->field_width[i] > data->column_maxwidth[i])
362 data->column_maxwidth[i] = entry->field_width[i];
368 static LONG FirstVisibleColumnNumber(struct TextIconList_DATA *data)
370 LONG i;
371 LONG retval = -1;
373 for(i = 0; i < NUM_COLUMNS; i++)
375 LONG index = data->column_pos[i];
377 if (data->column_visible[index])
379 retval = i;
380 break;
384 return retval;
387 static LONG LastVisibleColumnNumber(struct TextIconList_DATA *data)
389 LONG i;
390 LONG retval = -1;
392 for(i = 0; i < NUM_COLUMNS; i++)
394 LONG index = data->column_pos[i];
396 if (data->column_visible[index])
398 retval = i;
402 return retval;
406 static struct TextIconEntry *GetEntryFromIndex(struct TextIconList_DATA *data, LONG index)
408 struct TextIconEntry *node;
409 struct TextIconEntry *retval = 0;
410 ULONG i = 0;
412 if (index >= 0 && index < data->num_entries)
414 ForeachNode(&data->entries_list, node)
416 if (i == index)
418 retval = node;
419 break;
421 i++;
425 return retval;
428 static LONG LineUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
430 LONG index = -1;
432 if ((mx >= data->view_rect.MinX) &&
433 (my >= data->view_rect.MinY) &&
434 (mx <= data->view_rect.MaxX) &&
435 (my <= data->view_rect.MaxY))
437 index = (my - data->view_rect.MinY + data->view_y) / data->lineheight;
439 if ((index < 0) || (index >= data->num_entries)) index = -1;
442 return index;
445 static LONG ColumnUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
447 LONG col = -1;
449 if ((mx >= data->view_rect.MinX) &&
450 (my >= data->view_rect.MinY - data->headerheight) &&
451 (mx <= data->view_rect.MaxX) &&
452 (my <= data->view_rect.MaxY))
454 LONG x = data->view_rect.MinX - data->view_x + LINE_SPACING_LEFT;
455 LONG w, i;
457 for(i = 0; i < NUM_COLUMNS; i++)
459 LONG index = data->column_pos[i];
461 if (!data->column_visible[index]) continue;
463 w = data->column_width[index];
465 if ((mx >= x) && (mx < x + w))
467 col = index;
468 break;
470 x += w;
475 return col;
478 static LONG ColumnHeaderUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
480 LONG col = -1;
482 if (data->show_header &&
483 (my >= data->header_rect.MinY) &&
484 (my <= data->header_rect.MaxY))
486 col = ColumnUnderMouse(data, mx, my);
489 return col;
492 static LONG ColumnResizeHandleUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
494 LONG col = -1;
496 if ((mx >= data->view_rect.MinX) &&
497 (my >= data->view_rect.MinY - data->headerheight) &&
498 (mx <= data->view_rect.MaxX) &&
499 (my <= data->view_rect.MaxY))
501 LONG x = data->view_rect.MinX - data->view_x + LINE_SPACING_LEFT;
502 LONG w, i;
504 for(i = 0; i < NUM_COLUMNS; i++)
506 LONG index = data->column_pos[i];
508 if (!data->column_visible[index]) continue;
510 w = data->column_width[index];
512 if (abs(mx - (x + w - 1)) <= 4)
514 col = index;
515 break;
517 x += w;
522 return col;
525 static BOOL GetColumnCoords(struct TextIconList_DATA *data, LONG index, LONG *x1, LONG *x2)
527 LONG i;
528 BOOL retval = FALSE;
529 LONG x = data->view_rect.MinX - data->view_x + LINE_SPACING_LEFT;
530 LONG firstvis, lastvis;
532 firstvis = FirstVisibleColumnNumber(data);
533 lastvis = LastVisibleColumnNumber(data);
535 for(i = 0; i < NUM_COLUMNS; i++)
537 LONG idx = data->column_pos[i];
538 LONG w;
540 if (!data->column_visible[idx]) continue;
542 w = data->column_width[idx];
544 if (idx == index)
546 retval = TRUE;
547 *x1 = x - ((i == firstvis) ? LINE_SPACING_LEFT : 0);
548 *x2 = x + w - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
549 break;
552 x += w;
555 return retval;
558 static LONG CompareNodes(struct TextIconList_DATA *data, struct TextIconEntry *node1, struct TextIconEntry *node2)
560 LONG pri1 = (node1->fib.fib_DirEntryType > 0) ? 1 : 0;
561 LONG pri2 = (node2->fib.fib_DirEntryType > 0) ? 1 : 0;
562 LONG diff = (pri2 - pri1) * -(data->sort_dirs - 1);
564 if (!diff)
566 switch(data->sort_column)
568 case INDEX_DATE:
569 case INDEX_TIME:
570 diff = CompareDates((const struct DateStamp *)&node2->fib.fib_Date,
571 (const struct DateStamp *)&node1->fib.fib_Date);
573 break;
575 case INDEX_SIZE:
576 if (node1->fib.fib_Size < node2->fib.fib_Size)
578 diff = -1;
580 else if (node1->fib.fib_Size > node2->fib.fib_Size)
582 diff = 1;
584 break;
586 default:
587 case INDEX_NAME:
588 diff = Stricmp(node1->fib.fib_FileName, node2->fib.fib_FileName);
589 break;
593 if (data->sort_direction == SORT_DIRECTION_DOWN) diff = -diff;
596 return diff;
599 static void SortInNode(struct TextIconList_DATA *data, struct List *list, struct Node *node,
600 LONG (*compare)(APTR data, APTR node1, APTR node2))
602 struct Node *prevnode = NULL;
603 struct Node *checknode;
605 ForeachNode(list, checknode)
607 if (compare(data, node, checknode) < 0) break;
609 prevnode = checknode;
612 Insert(list, node, prevnode);
615 static void ReSortEntries(struct TextIconList_DATA *data)
617 struct List templist;
618 struct Node *node, *succ;
620 NEWLIST(&templist);
622 ForeachNodeSafe(&data->entries_list, node, succ)
624 Remove(node);
625 AddTail(&templist, node);
628 ForeachNodeSafe(&templist, node, succ)
630 SortInNode(data, (struct List *)&data->entries_list, node, (APTR)CompareNodes);
634 static BOOL MustRenderRect(struct TextIconList_DATA *data, struct Rectangle *rect)
636 if (data->update_rect1 && data->update_rect2)
638 if (!AndRectRect(rect, data->update_rect1, NULL) &&
639 !AndRectRect(rect, data->update_rect2, NULL)) return FALSE;
641 else if (data->update_rect1)
643 if (!AndRectRect(rect, data->update_rect1, NULL)) return FALSE;
645 else if (data->update_rect2)
647 if (!AndRectRect(rect, data->update_rect2, NULL)) return FALSE;
650 return TRUE;
653 static void GetAbsoluteLassoRect(struct TextIconList_DATA *data, struct Rectangle *lasso_rect)
655 WORD minx = data->lasso_rect.MinX;
656 WORD miny = data->lasso_rect.MinY;
657 WORD maxx = data->lasso_rect.MaxX;
658 WORD maxy = data->lasso_rect.MaxY;
660 if (minx > maxx)
662 /* Swap minx, maxx */
663 minx ^= maxx;
664 maxx ^= minx;
665 minx ^= maxx;
668 if (miny > maxy)
670 /* Swap miny, maxy */
671 miny ^= maxy;
672 maxy ^= miny;
673 miny ^= maxy;
676 lasso_rect->MinX = data->view_rect.MinX - data->view_x + minx;
677 lasso_rect->MinY = data->view_rect.MinY - data->view_y + miny;
678 lasso_rect->MaxX = data->view_rect.MinX - data->view_x + maxx;
679 lasso_rect->MaxY = data->view_rect.MinY - data->view_y + maxy;
682 static void EnableMouseMoveEvents(Object *obj, struct TextIconList_DATA *data)
684 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
686 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
687 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
688 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
692 static void DisableMouseMoveEvents(Object *obj, struct TextIconList_DATA *data)
694 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
696 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
697 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
698 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
702 static void EnableAutoScrollTimer(Object *obj, struct TextIconList_DATA *data)
704 if (!data->thn.ihn_Millis)
706 data->thn.ihn_Millis = AUTOSCROLL_MILLIS;
707 DoMethod(_app(obj), MUIM_Application_AddInputHandler, (IPTR)&data->thn);
711 static void DisableAutoScrollTimer(Object *obj, struct TextIconList_DATA *data)
713 if (data->thn.ihn_Millis)
715 data->thn.ihn_Millis = 0;
716 DoMethod(_app(obj), MUIM_Application_RemInputHandler, (IPTR)&data->thn);
720 static BOOL OrRectOutlineRegion(struct Region *reg, struct Rectangle *rect)
722 struct Rectangle r;
723 BOOL result;
725 r.MinX = rect->MinX;
726 r.MinY = rect->MinY;
727 r.MaxX = rect->MaxX;
728 r.MaxY = rect->MinY;
729 result = OrRectRegion(reg, &r);
731 r.MinX = rect->MaxX;
732 r.MinY = rect->MinY;
733 r.MaxX = rect->MaxX;
734 r.MaxY = rect->MaxY;
735 result = result && OrRectRegion(reg, &r);
737 r.MinX = rect->MinX;
738 r.MinY = rect->MaxY;
739 r.MaxX = rect->MaxX;
740 r.MaxY = rect->MaxY;
741 result = result && OrRectRegion(reg, &r);
743 r.MinX = rect->MinX;
744 r.MinY = rect->MinY;
745 r.MaxX = rect->MinX;
746 r.MaxY = rect->MaxY;
747 result = result && OrRectRegion(reg, &r);
749 return result;
752 static void MyRectFill(struct TextIconList_DATA *data, struct RastPort *rp,
753 LONG x1, LONG y1, LONG x2, LONG y2, LONG mycol)
755 if (x1 > x2)
757 x1 ^= x2;
758 x2 ^= x1;
759 x1 ^= x2;
762 if (y1 > y2)
764 y1 ^= y2;
765 y2 ^= y1;
766 y1 ^= y2;
769 SetDrMd(rp, JAM1);
771 if (data->truecolor && CyberGfxBase)
773 FillPixelArray(rp, x1, y1, x2 - x1 + 1, y2 - y1 + 1, data->colors[mycol].rgbpixel);
775 else
777 SetAPen(rp, data->colors[mycol].pixel);
778 RectFill(rp, x1, y1, x2, y2);
782 static void RenderHeaderField(Object *obj, struct TextIconList_DATA *data,
783 struct Rectangle *rect, LONG index)
785 STRPTR text;
786 struct TextExtent te;
787 ULONG fit;
788 BOOL sel = FALSE;
790 if ((data->inputstate == INPUTSTATE_COL_HEADER_CLICK) &&
791 (data->click_column == index))
794 if (ColumnHeaderUnderMouse(data, data->click_x, data->click_y) == index)
796 sel = TRUE;
800 text = GetTextIconHeaderText(data, index);
802 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_HALFSHADOW : MPEN_HALFSHINE]);
803 RectFill(_rp(obj), rect->MinX + 1, rect->MinY + 1,
804 rect->MaxX - 1, rect->MaxY - 1);
805 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_SHADOW : MPEN_SHINE]);
806 RectFill(_rp(obj), rect->MinX, rect->MinY, rect->MinX, rect->MaxY);
807 RectFill(_rp(obj), rect->MinX + 1, rect->MinY, rect->MaxX - 1, rect->MinY);
808 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_HALFSHINE : MPEN_HALFSHADOW]);
809 RectFill(_rp(obj), rect->MaxX, rect->MinY, rect->MaxX, rect->MaxY);
810 RectFill(_rp(obj), rect->MinX + 1, rect->MaxY, rect->MaxX - 1, rect->MaxY);
812 if (index == data->sort_column)
814 LONG x = rect->MaxX - 4 - 6;
815 LONG y = (rect->MinY + rect->MaxY + 1) / 2 - 3;
817 if (x > rect->MinX)
819 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_SHADOW : MPEN_HALFSHADOW]);
820 if (data->sort_direction == SORT_DIRECTION_UP)
822 RectFill(_rp(obj), x, y, x + 5, y + 1);
823 RectFill(_rp(obj), x + 1, y + 2, x + 4, y + 3);
824 RectFill(_rp(obj), x + 2, y + 4, x + 3, y + 5);
826 else
828 RectFill(_rp(obj), x, y + 4, x + 5, y + 5);
829 RectFill(_rp(obj), x + 1, y + 2, x + 4, y + 3);
830 RectFill(_rp(obj), x + 2, y, x + 3, y + 1);
835 rect->MinX += HEADERENTRY_SPACING_LEFT;
836 rect->MinY += HEADERLINE_SPACING_TOP;
837 rect->MaxX -= HEADERENTRY_SPACING_RIGHT;
838 rect->MaxY -= HEADERLINE_SPACING_BOTTOM;
840 if (text && text[0])
842 fit = TextFit(_rp(obj), text, strlen(text), &te, NULL, 1,
843 rect->MaxX - rect->MinX + 1,
844 rect->MaxY - rect->MinY + 1);
846 if (!fit) return;
848 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_TEXT], 0, JAM1);
849 Move(_rp(obj), rect->MinX, rect->MinY + _rp(obj)->TxBaseline);
850 Text(_rp(obj), text, fit);
855 static void RenderHeaderline(Object *obj, struct TextIconList_DATA *data)
857 struct Rectangle linerect;
858 LONG x, i;
859 LONG firstvis, lastvis;
860 linerect = data->header_rect;
861 linerect.MinX -= data->view_x;
862 linerect.MaxX -= data->view_x;
864 linerect.MinX = data->header_rect.MinX - data->view_x;
865 linerect.MaxX = data->header_rect.MaxX; //linerect.MinX + data->width - 1;
866 linerect.MinY = data->header_rect.MinY;
867 linerect.MaxY = data->header_rect.MaxY;
869 if (!MustRenderRect(data, &linerect)) return;
871 SetFont(_rp(obj), _font(obj));
873 x = linerect.MinX + HEADERLINE_SPACING_LEFT;
875 firstvis = FirstVisibleColumnNumber(data);
876 lastvis = LastVisibleColumnNumber(data);
878 for(i = 0; i < NUM_COLUMNS; i++)
880 struct Rectangle field_rect;
881 LONG index = data->column_pos[i];
883 if (!data->column_visible[index]) continue;
885 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
886 field_rect.MinY = linerect.MinY;
887 field_rect.MaxX = x + data->column_width[index] - 1 + ((i == lastvis) ? HEADERLINE_SPACING_RIGHT : 0);
888 field_rect.MaxY = linerect.MaxY;
890 if (MustRenderRect(data, &field_rect))
892 RenderHeaderField(obj, data, &field_rect, index);
894 x += data->column_width[index];
897 x += HEADERLINE_SPACING_RIGHT;
899 if (x < linerect.MaxX)
901 linerect.MinX = x;
903 if (MustRenderRect(data, &linerect))
905 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_HALFSHINE], 0, JAM1);
906 RectFill(_rp(obj), linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
912 #define ENTRYPOS_FIRST -1
913 #define ENTRYPOS_MIDDLE 0
914 #define ENTRYPOS_LAST 1
916 static void RenderEntryField(Object *obj, struct TextIconList_DATA *data,
917 struct TextIconEntry *entry, struct Rectangle *rect,
918 LONG index, BOOL firstvis, BOOL lastvis)
920 STRPTR text;
921 struct TextExtent te;
922 ULONG fit;
923 BOOL selected;
925 selected = (entry && data->column_clickable[index]) ? entry->selected : FALSE;
927 fit = selected ? COLOR_SELECTED_BACKGROUND : COLOR_COLUMN_BACKGROUND;
928 if (index == data->sort_column) fit++;
929 if (data->lasso_paint) fit += 2;
931 MyRectFill(data, _rp(obj), rect->MinX, rect->MinY, rect->MaxX, rect->MaxY, fit);
933 rect->MinX += ENTRY_SPACING_LEFT;
934 rect->MaxX -= ENTRY_SPACING_RIGHT;
935 rect->MinY += LINE_SPACING_TOP;
936 rect->MaxY -= LINE_SPACING_BOTTOM;
938 if (firstvis) rect->MinX += LINE_SPACING_LEFT;
939 if (lastvis) rect->MaxX -= LINE_SPACING_RIGHT;
941 if (!entry) return;
943 text = GetTextIconEntryText(data, entry, index);
944 if (!text) return;
945 if (!text[0]) return;
947 fit = TextFit(_rp(obj), text, strlen(text), &te, NULL, 1,
948 rect->MaxX - rect->MinX + 1,
949 rect->MaxY - rect->MinY + 1);
951 if (!fit) return;
953 SetABPenDrMd(_rp(obj), _pens(obj)[selected ? MPEN_SHINE : MPEN_TEXT], 0, JAM1);
955 switch(data->column_align[index])
957 case COLUMN_ALIGN_LEFT:
958 Move(_rp(obj), rect->MinX, rect->MinY + _rp(obj)->TxBaseline);
959 break;
961 case COLUMN_ALIGN_RIGHT:
962 Move(_rp(obj), rect->MaxX - te.te_Width, rect->MinY + _rp(obj)->TxBaseline);
963 break;
965 case COLUMN_ALIGN_CENTER:
966 Move(_rp(obj), rect->MinX + (rect->MaxX - rect->MinX + 1 + 1 - te.te_Width) / 2,
967 rect->MinY + _rp(obj)->TxBaseline);
968 break;
971 Text(_rp(obj), text, fit);
974 static void RenderEntry(Object *obj, struct TextIconList_DATA *data, LONG index)
976 struct TextIconEntry *entry = GetEntryFromIndex(data, index);
977 struct Rectangle linerect;
978 LONG x, i;
979 LONG firstvis, lastvis;
981 linerect.MinX = data->view_rect.MinX - data->view_x;
982 linerect.MaxX = data->view_rect.MaxX; //linerect.MinX + data->width - 1;
983 linerect.MinY = data->view_rect.MinY + index * data->lineheight - data->view_y;
984 linerect.MaxY = linerect.MinY + data->lineheight - 1;
986 if (!AndRectRect(&linerect, &data->view_rect, NULL)) return;
987 if (!MustRenderRect(data, &linerect)) return;
989 SetFont(_rp(obj), _font(obj));
991 x = linerect.MinX + LINE_SPACING_LEFT;
993 firstvis = FirstVisibleColumnNumber(data);
994 lastvis = LastVisibleColumnNumber(data);
996 for(i = 0; i < NUM_COLUMNS; i++)
998 struct Rectangle field_rect;
999 LONG index = data->column_pos[i];
1001 if (!data->column_visible[i]) continue;
1003 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
1004 field_rect.MinY = linerect.MinY;
1005 field_rect.MaxX = x + data->column_width[index] - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
1006 field_rect.MaxY = linerect.MaxY;
1008 if (MustRenderRect(data, &field_rect))
1010 if (AndRectRect(&field_rect, &data->view_rect, NULL))
1012 RenderEntryField(obj, data, entry, &field_rect, index,
1013 (i == firstvis), (i == lastvis));
1016 x += data->column_width[index];
1019 x += LINE_SPACING_RIGHT;
1021 if (x < linerect.MaxX)
1023 linerect.MinX = x;
1025 if (MustRenderRect(data, &linerect))
1027 SetABPenDrMd(_rp(obj), _pens(obj)[data->lasso_paint ? MPEN_BACKGROUND : MPEN_SHINE], 0, JAM1);
1028 RectFill(_rp(obj), linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
1034 static LONG FirstVisibleLine(struct TextIconList_DATA *data)
1036 return data->view_y / data->lineheight;
1039 static LONG NumVisibleLines(struct TextIconList_DATA *data)
1041 LONG visible = data->view_height + data->lineheight - 1 +
1042 (data->view_y % data->lineheight);
1044 visible /= data->lineheight;
1046 return visible;
1049 static void RenderAllEntries(Object *obj, struct TextIconList_DATA *data)
1051 LONG first = FirstVisibleLine(data);
1052 LONG visible = NumVisibleLines(data);
1053 LONG i;
1055 for(i = 0; i < visible; i++)
1057 RenderEntry(obj, data, first + i);
1063 static void RethinkLasso(Object *obj, struct TextIconList_DATA *data)
1065 struct TextIconEntry *entry;
1067 LONG ny1 = data->lasso_rect.MinY;
1068 LONG ny2 = data->lasso_rect.MaxY;
1069 LONG oy1 = data->old_lasso_rect.MinY;
1070 LONG oy2 = data->old_lasso_rect.MaxY;
1071 LONG y1, y2;
1072 LONG x1, x2;
1073 LONG numdirty = 0;
1074 BOOL lasso_hot;
1076 if (!data->num_entries) return;
1078 if (ny1 > ny2)
1080 ny1 ^= ny2;
1081 ny2 ^= ny1;
1082 ny1 ^= ny2;
1085 if (oy1 > oy2)
1087 oy1 ^= oy2;
1088 oy2 ^= oy1;
1089 oy1 ^= oy2;
1092 ny1 /= data->lineheight;
1093 ny2 /= data->lineheight;
1094 oy1 /= data->lineheight;
1095 oy2 /= data->lineheight;
1097 y1 = (ny1 < oy1) ? ny1 : oy1;
1098 y2 = (ny2 > oy2) ? ny2 : oy2;
1100 if (y1 < 0)
1102 y1 = 0;
1104 else if (y1 >= data->num_entries)
1106 y1 = data->num_entries - 1;
1109 if (y2 < 0)
1111 y2 = 0;
1113 else if (y2 >= data->num_entries)
1115 y2 = data->num_entries - 1;
1118 GetColumnCoords(data, INDEX_NAME, &x1, &x2);
1119 x1 += data->view_x - data->view_rect.MinX;
1120 x2 += data->view_x - data->view_rect.MinX;
1122 lasso_hot = ((data->lasso_rect.MinX >= x1) && (data->lasso_rect.MinX <= x2)) ||
1123 ((data->lasso_rect.MaxX >= x1) && (data->lasso_rect.MaxX <= x2)) ||
1124 ((data->lasso_rect.MinX < x1) && (data->lasso_rect.MaxX > x2)) ||
1125 ((data->lasso_rect.MaxX < x1) && (data->lasso_rect.MinX > x2));
1127 entry = GetEntryFromIndex(data, y1);
1128 while(entry && entry->node.mln_Succ && (y1 <= y2))
1130 BOOL select;
1132 select = (y1 >= ny1) && (y1 <= ny2) && lasso_hot;
1133 if (select != entry->selected)
1135 if (select)
1137 AddTail((struct List *)&data->selection_list, (struct Node *)&entry->selection_node);
1138 data->num_selected++;
1140 else
1142 Remove((struct Node *)&entry->selection_node);
1143 data->num_selected--;
1145 entry->selected = select;
1146 entry->dirty = TRUE;
1147 numdirty++;
1150 entry = (struct TextIconEntry *)entry->node.mln_Succ;
1151 y1++;
1154 if (numdirty)
1156 data->update = UPDATE_DIRTY_ENTRIES;
1157 MUI_Redraw(obj, MADF_DRAWUPDATE);
1162 /**************************************************************************
1163 OM_NEW
1164 **************************************************************************/
1165 static IPTR TextIconList_New(struct IClass *cl, Object *obj, struct opSet *msg)
1167 struct TextIconList_DATA *data;
1168 struct TagItem *tag, *tags;
1169 LONG i;
1171 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
1172 MUIA_FillArea, FALSE,
1173 TAG_MORE, (IPTR) msg->ops_AttrList);
1174 if (!obj) return FALSE;
1176 data = INST_DATA(cl, obj);
1177 NewList((struct List*)&data->entries_list);
1178 NewList((struct List*)&data->selection_list);
1179 data->show_header = TRUE;
1180 data->active_entry = -1;
1182 for(i = 0; i < NUM_COLUMNS; i++)
1184 data->column_pos[i] = i;
1185 data->column_visible[i] = TRUE;
1186 data->column_width[i] = 100;
1188 data->column_align[INDEX_SIZE] = COLUMN_ALIGN_RIGHT;
1189 data->column_clickable[INDEX_NAME] = TRUE;
1191 data->column_sortable[INDEX_NAME] = TRUE;
1192 data->column_sortable[INDEX_SIZE] = TRUE;
1193 data->column_sortable[INDEX_DATE] = TRUE;
1194 data->column_sortable[INDEX_TIME] = TRUE;
1196 data->sort_column = INDEX_NAME;
1197 data->sort_direction = SORT_DIRECTION_UP;
1198 data->sort_dirs = SORT_DRAWERS_FIRST;
1200 /* parse initial taglist */
1201 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
1203 switch (tag->ti_Tag)
1208 data->pool = CreatePool(0,4096,4096);
1209 if (!data->pool)
1211 CoerceMethod(cl,obj,OM_DISPOSE);
1212 return 0;
1215 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1216 data->ehn.ehn_Priority = 0;
1217 data->ehn.ehn_Flags = 0;
1218 data->ehn.ehn_Object = obj;
1219 data->ehn.ehn_Class = cl;
1221 data->thn.ihn_Flags = MUIIHNF_TIMER;
1222 data->thn.ihn_Method = MUIM_TextIconList_AutoScroll;
1223 data->thn.ihn_Object = obj;
1225 return (IPTR)obj;
1228 /**************************************************************************
1229 OM_DISPOSE
1230 **************************************************************************/
1231 static IPTR TextIconList_Dispose(struct IClass *cl, Object *obj, Msg msg)
1233 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1234 struct TextIconEntry *node;
1236 ForeachNode(&data->entries_list, node)
1240 if (data->pool) DeletePool(data->pool);
1242 DoSuperMethodA(cl,obj,msg);
1243 return 0;
1246 /**************************************************************************
1247 OM_SET
1248 **************************************************************************/
1249 static IPTR TextIconList_Set(struct IClass *cl, Object *obj, struct opSet *msg)
1251 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1252 struct TagItem *tag, *tags;
1253 LONG oldleft = data->view_x, oldtop = data->view_y;
1255 /* parse initial taglist */
1256 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
1258 switch (tag->ti_Tag)
1260 case MUIA_TextIconList_Left:
1261 if (data->view_x != (LONG)tag->ti_Data)
1263 LONG new_view_x = (LONG)tag->ti_Data;
1265 if (new_view_x + data->view_width > data->width)
1267 new_view_x = data->width - data->view_width;
1269 if (new_view_x < 0) new_view_x = 0;
1271 data->view_x = new_view_x;
1272 tag->ti_Data = new_view_x;
1274 break;
1276 case MUIA_TextIconList_Top:
1277 if (data->view_y != (LONG)tag->ti_Data)
1279 LONG new_view_y = (LONG)tag->ti_Data;
1281 if (new_view_y + data->view_height > data->height)
1283 new_view_y = data->height - data->view_height;
1285 if (new_view_y < 0) new_view_y = 0;
1287 data->view_y = new_view_y;
1288 tag->ti_Data = new_view_y;
1290 break;
1294 if ((oldleft != data->view_x) || (oldtop != data->view_y))
1296 data->update = UPDATE_SCROLL;
1297 data->update_scrolldx = data->view_x - oldleft;
1298 data->update_scrolldy = data->view_y - oldtop;
1300 MUI_Redraw(obj, MADF_DRAWUPDATE);
1303 return DoSuperMethodA(cl, obj, (Msg)msg);
1306 /**************************************************************************
1307 OM_GET
1308 **************************************************************************/
1309 static IPTR TextIconList_Get(struct IClass *cl, Object *obj, struct opGet *msg)
1311 /* small macro to simplify return value storage */
1312 #define STORE *(msg->opg_Storage)
1313 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1315 switch (msg->opg_AttrID)
1317 case MUIA_TextIconList_Left: STORE = data->view_x; return 1;
1318 case MUIA_TextIconList_Top: STORE = data->view_y; return 1;
1319 case MUIA_TextIconList_Width: STORE = data->width; return 1;
1320 case MUIA_TextIconList_Height: STORE = data->height; return 1;
1323 return DoSuperMethodA(cl, obj, (Msg) msg);
1324 #undef STORE
1327 /**************************************************************************
1328 MUIM_Setup
1329 **************************************************************************/
1330 static IPTR TextIconList_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
1332 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1333 LONG i;
1335 if (!DoSuperMethodA(cl, obj, (Msg) msg)) return 0;
1337 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1339 InitRastPort(&data->temprp);
1340 SetFont(&data->temprp, _font(obj));
1341 data->truecolor = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH) >= 15;
1343 data->lineheight = LINE_EXTRAHEIGHT + _font(obj)->tf_YSize;
1344 data->is_setup = TRUE;
1346 for(i = 0; i < NUM_COLORS; i++)
1348 data->colors[i].rgbpixel = rgb_colors[i];
1349 data->colors[i].pixel = data->colors[i].rgbpixel;
1351 if (!data->truecolor || !CyberGfxBase)
1353 ULONG r = (rgb_colors[i] & 0x00FF0000) >> 16;
1354 ULONG g = (rgb_colors[i] & 0x0000FF00) >> 8;
1355 ULONG b = (rgb_colors[i] & 0x000000FF);
1357 LONG pen = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,
1358 r * 0x01010101,
1359 g * 0x01010101,
1360 b * 0x01010101,
1361 OBP_FailIfBad, FALSE,
1362 OBP_Precision, PRECISION_GUI,
1363 TAG_DONE);
1365 if (pen >= 0)
1367 data->colors[i].pixel = pen;
1368 data->colors[i].alloced = TRUE;
1370 else
1372 data->colors[i].pixel = _pens(obj)[pen_colors[i]];
1373 data->colors[i].alloced = FALSE;
1378 if (data->show_header)
1380 data->headerheight = HEADERLINE_EXTRAHEIGHT + _font(obj)->tf_YSize;
1382 else
1384 data->headerheight = 0;
1387 if (data->num_entries)
1389 CalcAllEntryDimensions(data);
1390 CalcWidth(data);
1391 data->height = data->num_entries * data->lineheight;
1392 RecalcColumnMaxWidths(data);
1394 SetAttrs(obj, MUIA_TextIconList_Width, data->width,
1395 MUIA_TextIconList_Height, data->height,
1396 TAG_DONE);
1399 return 1;
1402 /**************************************************************************
1403 MUIM_Show
1404 **************************************************************************/
1405 static IPTR TextIconList_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
1407 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1408 LONG newleft, newtop;
1409 IPTR rc;
1411 rc = DoSuperMethodA(cl, obj, (Msg)msg);
1413 newleft = data->view_x;
1414 newtop = data->view_y;
1416 data->view_width = _mwidth(obj);
1417 data->view_height = _mheight(obj) - data->headerheight;
1419 SetAttrs(obj, MUIA_TextIconList_VisWidth, data->view_width,
1420 MUIA_TextIconList_VisHeight, data->view_height,
1421 TAG_DONE);
1423 data->view_rect.MinX = _mleft(obj);
1424 data->view_rect.MinY = _mtop(obj) + data->headerheight;
1425 data->view_rect.MaxX = _mright(obj);
1426 data->view_rect.MaxY = _mbottom(obj);
1428 data->header_rect.MinX = _mleft(obj);
1429 data->header_rect.MinY = _mtop(obj);
1430 data->header_rect.MaxX = _mright(obj);
1431 data->header_rect.MaxY = _mtop(obj) + data->headerheight - 1;
1433 if (newleft + data->view_width > data->width) newleft = data->width - data->view_width;
1434 if (newleft < 0) newleft = 0;
1436 if (newtop + data->view_height > data->height) newtop = data->height - data->view_height;
1437 if (newtop < 0) newtop = 0;
1439 if ((newleft != data->view_x) || (newtop != data->view_y))
1441 SetAttrs(obj, MUIA_TextIconList_Left, newleft,
1442 MUIA_TextIconList_Top, newtop,
1443 TAG_DONE);
1446 SetFont(_rp(obj), _font(obj));
1448 data->is_shown = TRUE;
1450 return rc;
1453 /**************************************************************************
1454 MUIM_Hide
1455 **************************************************************************/
1456 static IPTR TextIconList_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
1458 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1459 IPTR rc;
1461 data->is_shown = FALSE;
1463 rc = DoSuperMethodA(cl, obj, (Msg)msg);
1465 return rc;
1468 /**************************************************************************
1469 MUIM_Cleanup
1470 **************************************************************************/
1471 static IPTR TextIconList_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
1473 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1474 LONG i;
1476 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1478 DeinitRastPort(&data->temprp);
1480 for(i = 0; i < NUM_COLORS; i++)
1482 if (data->colors[i].alloced)
1484 ReleasePen(_screen(obj)->ViewPort.ColorMap, data->colors[i].pixel);
1485 data->colors[i].alloced = FALSE;
1489 data->is_setup = FALSE;
1491 return DoSuperMethodA(cl, obj, (Msg) msg);
1494 /**************************************************************************
1495 MUIM_AskMinMax
1496 **************************************************************************/
1497 static IPTR TextIconList_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
1499 ULONG rc = DoSuperMethodA(cl, obj, (Msg) msg);
1501 msg->MinMaxInfo->MinWidth += 10;
1502 msg->MinMaxInfo->MinHeight += 10;
1504 msg->MinMaxInfo->DefWidth += 100;
1505 msg->MinMaxInfo->DefHeight += 100;
1507 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
1508 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
1510 return rc;
1513 static void DrawHeaderLine(Object *obj, struct TextIconList_DATA *data)
1515 APTR clip;
1517 if (data->show_header && MustRenderRect(data, &data->header_rect))
1519 clip = MUI_AddClipping(muiRenderInfo(obj), data->header_rect.MinX,
1520 data->header_rect.MinY,
1521 data->header_rect.MaxX - data->header_rect.MinX + 1,
1522 data->header_rect.MaxY - data->header_rect.MinY + 1);
1524 RenderHeaderline(obj, data);
1526 MUI_RemoveClipping(muiRenderInfo(obj),clip);
1530 static void DrawLassoOutline(Object *obj, struct TextIconList_DATA *data)
1532 struct Rectangle lasso;
1534 GetAbsoluteLassoRect(data, &lasso);
1536 #if 1
1537 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MinY, lasso.MaxX, lasso.MinY, COLOR_SELECTED_BACKGROUND);
1538 MyRectFill(data, _rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1539 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1540 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MinY, lasso.MinX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1541 #else
1542 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_SHADOW], 0, JAM1);
1543 Move(_rp(obj), lasso.MinX, lasso.MinY);
1544 Draw(_rp(obj), lasso.MaxX, lasso.MinY);
1545 Draw(_rp(obj), lasso.MaxX, lasso.MaxY);
1546 Draw(_rp(obj), lasso.MinX, lasso.MaxY);
1547 Draw(_rp(obj), lasso.MinX, lasso.MinY);
1548 #endif
1551 /**************************************************************************
1552 MUIM_Draw
1553 **************************************************************************/
1554 static IPTR TextIconList_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
1556 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1557 APTR clip;
1558 struct TextIconEntry *entry;
1560 DoSuperMethodA(cl, obj, (Msg) msg);
1562 if (msg->flags & MADF_DRAWUPDATE)
1564 if (data->update == UPDATE_SCROLL)
1566 struct Region *region;
1567 struct Rectangle xrect, yrect;
1568 BOOL scroll_caused_damage;
1570 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
1572 data->update = 0;
1574 if ((abs(data->update_scrolldx) >= data->view_width) ||
1575 (abs(data->update_scrolldy) >= data->view_height))
1577 data->update = UPDATE_ALL;
1578 MUI_Redraw(obj, MADF_DRAWUPDATE);
1579 return 0;
1582 region = NewRegion();
1583 if (!region)
1585 data->update = UPDATE_ALL;
1586 MUI_Redraw(obj, MADF_DRAWUPDATE);
1587 return 0;
1590 if (data->update_scrolldx > 0)
1592 xrect.MinX = data->view_rect.MaxX - data->update_scrolldx;
1593 xrect.MinY = data->view_rect.MinY;
1594 xrect.MaxX = data->view_rect.MaxX;
1595 xrect.MaxY = data->view_rect.MaxY;
1597 OrRectRegion(region, &xrect);
1599 data->update_rect1 = &xrect;
1601 else if (data->update_scrolldx < 0)
1603 xrect.MinX = data->view_rect.MinX;
1604 xrect.MinY = data->view_rect.MinY;
1605 xrect.MaxX = data->view_rect.MinX - data->update_scrolldx;
1606 xrect.MaxY = data->view_rect.MaxY;
1608 OrRectRegion(region, &xrect);
1610 data->update_rect1 = &xrect;
1613 if (data->update_scrolldy > 0)
1615 yrect.MinX = data->view_rect.MinX;
1616 yrect.MinY = data->view_rect.MaxY - data->update_scrolldy;
1617 yrect.MaxX = data->view_rect.MaxX;
1618 yrect.MaxY = data->view_rect.MaxY;
1620 OrRectRegion(region, &yrect);
1622 data->update_rect2 = &yrect;
1624 else if (data->update_scrolldy < 0)
1626 yrect.MinX = data->view_rect.MinX;
1627 yrect.MinY = data->view_rect.MinY;
1628 yrect.MaxX = data->view_rect.MaxX;
1629 yrect.MaxY = data->view_rect.MinY - data->update_scrolldy;
1631 OrRectRegion(region, &yrect);
1633 data->update_rect2 = &yrect;
1636 ScrollRasterBF(_rp(obj),
1637 data->update_scrolldx,
1638 data->update_scrolldy,
1639 data->view_rect.MinX,
1640 data->view_rect.MinY,
1641 data->view_rect.MaxX,
1642 data->view_rect.MaxY);
1644 if (data->show_header && data->update_scrolldx)
1646 ScrollRasterBF(_rp(obj),
1647 data->update_scrolldx,
1649 data->header_rect.MinX,
1650 data->header_rect.MinY,
1651 data->header_rect.MaxX,
1652 data->header_rect.MaxY);
1655 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
1657 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1658 data->update = UPDATE_ALL;
1659 MUI_Redraw(obj, MADF_DRAWUPDATE);
1660 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1662 if (data->show_header && data->update_scrolldx)
1664 xrect.MinY = data->header_rect.MinY;
1665 xrect.MaxY = data->header_rect.MaxY;
1667 data->update_rect1 = &xrect;
1668 data->update_rect2 = NULL;
1670 clip = MUI_AddClipping(muiRenderInfo(obj), xrect.MinX,
1671 xrect.MinY,
1672 xrect.MaxX - xrect.MinX + 1,
1673 xrect.MaxY - xrect.MinY + 1);
1675 data->update = UPDATE_ALL;
1676 MUI_Redraw(obj, MADF_DRAWUPDATE);
1677 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1679 data->update_rect2 = NULL;
1683 data->update_rect1 = data->update_rect2 = NULL;
1684 data->update_scrolldx = data->update_scrolldy = 0;
1686 // DisposeRegion(region);
1688 if (scroll_caused_damage)
1690 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
1692 /* Theoretically it might happen that more damage is caused
1693 after ScrollRaster. By something else, like window movement
1694 in front of our window. Therefore refresh root object of
1695 window, not just this object */
1697 Object *o;
1699 get(_win(obj),MUIA_Window_RootObject, &o);
1700 MUI_Redraw(o, MADF_DRAWOBJECT);
1702 MUI_EndRefresh(muiRenderInfo(obj), 0);
1706 return 0;
1708 } /* if (data->update == UPDATE_SCROLL) */
1709 else if (data->update == UPDATE_DIRTY_ENTRIES)
1711 struct Region *clipregion;
1712 LONG first, numvisible, index = 0;
1714 data->update = 0;
1716 clipregion = NewRectRegion(data->view_rect.MinX,
1717 data->view_rect.MinY,
1718 data->view_rect.MaxX,
1719 data->view_rect.MaxY);
1721 if (clipregion)
1723 if (data->lasso_active)
1725 struct Rectangle lasso_rect;
1727 GetAbsoluteLassoRect(data, &lasso_rect);
1728 ClearRectRegion(clipregion, &lasso_rect);
1731 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1733 first = FirstVisibleLine(data);
1734 numvisible = NumVisibleLines(data);
1736 ForeachNode(&data->entries_list, entry)
1738 if (entry->dirty)
1740 if ((index >= first) && (index < first + numvisible))
1742 RenderEntry(obj, data, index);
1745 index++;
1748 if (data->lasso_active)
1750 struct Rectangle lasso_rect;
1751 struct Rectangle vis_lasso_rect;
1753 GetAbsoluteLassoRect(data, &lasso_rect);
1755 if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect))
1757 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1759 clipregion = NewRectRegion(vis_lasso_rect.MinX,
1760 vis_lasso_rect.MinY,
1761 vis_lasso_rect.MaxX,
1762 vis_lasso_rect.MaxY);
1764 data->lasso_paint = TRUE;
1766 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1768 index = 0;
1769 ForeachNode(&data->entries_list, entry)
1771 if (entry->dirty)
1773 if ((index >= first) && (index < first + numvisible))
1775 RenderEntry(obj, data, index);
1778 index++;
1781 data->lasso_paint = FALSE;
1783 DrawLassoOutline(obj, data);
1785 } /* if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect)) */
1787 } /* if (data->lasso_active) */
1789 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1791 ForeachNode(&data->entries_list, entry)
1793 if (entry->dirty) entry->dirty = FALSE;
1795 return 0;
1798 } /* else if (data->update == UPDATE_DIRTY_ENTRIES) */
1799 else if (data->update == UPDATE_HEADER)
1801 data->update = 0;
1803 DrawHeaderLine(obj, data);
1805 return 0;
1808 } /* if (msg->flags & MADF_DRAWUPDATE) */
1810 if (MustRenderRect(data, &data->view_rect))
1812 struct Region *clipregion;
1814 clipregion = NewRectRegion(data->view_rect.MinX,
1815 data->view_rect.MinY,
1816 data->view_rect.MaxX,
1817 data->view_rect.MaxY);
1819 if (clipregion)
1821 if (data->lasso_active)
1823 struct Rectangle lasso_rect;
1825 GetAbsoluteLassoRect(data, &lasso_rect);
1826 ClearRectRegion(clipregion, &lasso_rect);
1829 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1831 RenderAllEntries(obj, data);
1833 if (data->lasso_active)
1835 struct Rectangle lasso_rect;
1836 struct Rectangle vis_lasso_rect;
1838 GetAbsoluteLassoRect(data, &lasso_rect);
1840 if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect))
1842 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1844 clipregion = NewRectRegion(vis_lasso_rect.MinX,
1845 vis_lasso_rect.MinY,
1846 vis_lasso_rect.MaxX,
1847 vis_lasso_rect.MaxY);
1849 data->lasso_paint = TRUE;
1851 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1853 RenderAllEntries(obj, data);
1855 data->lasso_paint = FALSE;
1857 DrawLassoOutline(obj, data);
1862 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1864 } /* if (clipregion) */
1866 } /* if (MustRenderRect(data, &data->view_rect)) */
1868 DrawHeaderLine(obj, data);
1870 data->update = 0;
1872 return 0;
1875 /**************************************************************************
1876 MUIM_Draw
1877 **************************************************************************/
1878 static IPTR TextIconList_AutoScroll(struct IClass *cl, Object *obj, Msg msg)
1880 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1882 if (data->lasso_active)
1884 LONG new_view_x, new_view_y;
1886 new_view_x = data->view_x;
1887 new_view_y = data->view_y;
1889 if (data->click_x < data->view_rect.MinX)
1891 new_view_x -= (data->view_rect.MinX - data->click_x) / 4;
1893 else if (data->click_x > data->view_rect.MaxX)
1895 new_view_x += (data->click_x - data->view_rect.MaxX) / 4;
1898 if (data->click_y < data->view_rect.MinY)
1900 new_view_y -= (data->view_rect.MinY - data->click_y) / 4;
1902 else if (data->click_y > data->view_rect.MaxY)
1904 new_view_y += (data->click_y - data->view_rect.MaxY) / 4;
1907 if (new_view_x + data->view_width > data->width)
1909 new_view_x = data->width - data->view_width;
1911 if (new_view_x < 0) new_view_x = 0;
1913 if (new_view_y + data->view_height > data->height)
1915 new_view_y = data->height - data->view_height;
1917 if (new_view_y < 0) new_view_y = 0;
1919 if ((new_view_x != data->view_x) || (new_view_y != data->view_y))
1921 data->old_lasso_rect = data->lasso_rect;
1923 data->lasso_rect.MaxX += new_view_x - data->view_x;
1924 data->lasso_rect.MaxY += new_view_y - data->view_y;
1926 RethinkLasso(obj, data);
1928 SetAttrs(obj, MUIA_TextIconList_Left, new_view_x,
1929 MUIA_TextIconList_Top, new_view_y,
1930 TAG_DONE);
1934 else
1936 DisableAutoScrollTimer(obj, data);
1939 return 0;
1942 /**************************************************************************
1943 MUIM_HandleEvent
1944 **************************************************************************/
1945 static IPTR TextIconList_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
1947 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1948 IPTR retval = 0;
1950 if (msg->imsg)
1952 LONG mx = msg->imsg->MouseX;
1953 LONG my = msg->imsg->MouseY;
1954 LONG line, col;
1955 BOOL shift_qual;
1957 shift_qual = (msg->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? TRUE : FALSE;
1959 switch (msg->imsg->Class)
1961 case IDCMP_MOUSEBUTTONS:
1962 switch(msg->imsg->Code)
1964 case SELECTDOWN:
1965 //kprintf("SELECTDOWN\n");
1966 if (data->inputstate == INPUTSTATE_NONE)
1968 if ( ((line = LineUnderMouse(data, mx, my)) >= 0) &&
1969 ((col = ColumnUnderMouse(data, mx, my)) >= 0) )
1971 //kprintf("click on line %d col %d\n", line, col);
1973 if (data->column_clickable[col])
1975 if (data->active_entry != line)
1977 struct TextIconEntry *old, *new;
1979 old = GetEntryFromIndex(data, data->active_entry);
1980 new = GetEntryFromIndex(data, line);
1982 data->active_entry = line;
1983 if (old && old->selected && !shift_qual)
1985 Remove((struct Node *)&old->selection_node);
1986 old->selected = FALSE;
1987 old->dirty = TRUE;
1989 data->num_selected--;
1992 if (!shift_qual && data->num_selected)
1994 struct TextIconEntry *entry;
1996 ForeachNode(&data->entries_list, entry)
1998 if (entry->selected)
2000 Remove((struct Node *)&entry->selection_node);
2001 entry->selected = FALSE;
2002 entry->dirty = TRUE;
2006 data->num_selected = 0;
2009 if (new && !new->selected)
2011 AddTail((struct List *)&data->selection_list, (struct Node *)&new->selection_node);
2012 new->selected = TRUE;
2013 new->dirty = TRUE;
2015 data->num_selected++;
2018 data->update = UPDATE_DIRTY_ENTRIES;
2019 MUI_Redraw(obj, MADF_DRAWUPDATE);
2021 } /* if (data->active_entry != line) */
2023 } /* if (data->column_clickable[col]) */
2024 else
2026 if (!shift_qual && data->num_selected)
2028 struct TextIconEntry *entry;
2030 ForeachNode(&data->entries_list, entry)
2032 if (entry->selected)
2034 Remove((struct Node *)&entry->selection_node);
2035 entry->selected = FALSE;
2036 entry->dirty = TRUE;
2040 data->num_selected = 0;
2041 data->update = UPDATE_DIRTY_ENTRIES;
2042 MUI_Redraw(obj, MADF_DRAWUPDATE);
2045 data->lasso_rect.MinX = mx - data->view_rect.MinX + data->view_x;
2046 data->lasso_rect.MinY = my - data->view_rect.MinY + data->view_y;
2047 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
2048 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
2050 data->inputstate = INPUTSTATE_LASSO;
2051 data->lasso_active = TRUE;
2053 data->click_x = mx;
2054 data->click_y = my;
2056 EnableMouseMoveEvents(obj, data);
2059 } /* if click on entry */
2060 else if ((col = ColumnResizeHandleUnderMouse(data, mx, my)) >= 0)
2062 data->inputstate = INPUTSTATE_COL_RESIZE;
2063 data->click_column = col;
2064 data->click_x = mx - data->column_width[col];
2066 EnableMouseMoveEvents(obj, data);
2068 } /* else if click on column header entry resize handle */
2069 else if ((col = ColumnHeaderUnderMouse(data, mx, my)) >= 0)
2071 data->inputstate = INPUTSTATE_COL_HEADER_CLICK;
2072 data->click_column = col;
2073 data->click_x = mx;
2074 data->click_y = my;
2076 EnableMouseMoveEvents(obj, data);
2078 data->update = UPDATE_HEADER;
2079 MUI_Redraw(obj, MADF_DRAWUPDATE);
2082 } /* if (data->inputstate == INPUTSTATE_NONE) */
2083 break;
2085 case SELECTUP:
2086 if (data->inputstate == INPUTSTATE_COL_RESIZE)
2088 DisableMouseMoveEvents(obj, data);
2090 data->inputstate = INPUTSTATE_NONE;
2092 else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK)
2094 DisableMouseMoveEvents(obj, data);
2096 data->inputstate = INPUTSTATE_NONE;
2098 if (ColumnHeaderUnderMouse(data, data->click_x, data->click_y) == data->click_column)
2101 if (data->column_sortable[data->click_column])
2103 if (data->sort_column == data->click_column)
2105 data->sort_direction = 1 - data->sort_direction;
2107 else
2109 data->sort_direction = SORT_DIRECTION_UP;
2110 data->sort_column = data->click_column;
2113 ReSortEntries(data);
2115 data->update = UPDATE_ALL;
2116 MUI_Redraw(obj, MADF_DRAWUPDATE);
2119 else
2121 data->update = UPDATE_HEADER;
2122 MUI_Redraw(obj, MADF_DRAWUPDATE);
2125 } /* mouse still over column header */
2127 } /* else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK) */
2128 else if (data->inputstate == INPUTSTATE_LASSO)
2130 DisableMouseMoveEvents(obj, data);
2131 DisableAutoScrollTimer(obj, data);
2133 data->inputstate = INPUTSTATE_NONE;
2134 data->lasso_active = FALSE;
2136 data->update = UPDATE_ALL;
2137 MUI_Redraw(obj, MADF_DRAWUPDATE);
2139 break;
2141 case MIDDLEDOWN:
2142 if (data->inputstate == INPUTSTATE_NONE)
2144 data->inputstate = INPUTSTATE_PAN;
2146 data->click_x = mx - data->view_rect.MinX + data->view_x;
2147 data->click_y = my - data->view_rect.MinY + data->view_y;
2149 EnableMouseMoveEvents(obj, data);
2152 break;
2154 case MIDDLEUP:
2155 if (data->inputstate == INPUTSTATE_PAN)
2157 DisableMouseMoveEvents(obj, data);
2159 data->inputstate = INPUTSTATE_NONE;
2161 break;
2163 } /* switch(msg->imsg->Code) */
2164 break;
2166 case IDCMP_MOUSEMOVE:
2167 if (data->inputstate == INPUTSTATE_PAN)
2169 LONG new_view_x, new_view_y;
2171 new_view_x = data->click_x - (mx - data->view_rect.MinX);
2172 new_view_y = data->click_y - (my - data->view_rect.MinY);
2174 if (new_view_x + data->view_width > data->width)
2176 new_view_x = data->width - data->view_width;
2178 if (new_view_x < 0) new_view_x = 0;
2180 if (new_view_y + data->view_height > data->height)
2182 new_view_y = data->height - data->view_height;
2184 if (new_view_y < 0) new_view_y = 0;
2186 if ((new_view_x != data->view_x) || (new_view_y != data->view_y))
2188 SetAttrs(obj, MUIA_TextIconList_Left, new_view_x,
2189 MUIA_TextIconList_Top, new_view_y,
2190 TAG_DONE);
2193 } /* if (data->inputstate == INPUTSTATE_PAN) */
2194 else if (data->inputstate == INPUTSTATE_COL_RESIZE)
2196 LONG act_colwidth = data->column_width[data->click_column];
2197 LONG new_colwidth = mx - data->click_x;
2199 if (new_colwidth < MIN_COLUMN_WIDTH) new_colwidth = MIN_COLUMN_WIDTH;
2201 if (new_colwidth > act_colwidth)
2203 data->column_width[data->click_column] = new_colwidth;
2204 data->width += new_colwidth - act_colwidth;
2205 data->update = UPDATE_ALL;
2206 MUI_Redraw(obj, MADF_DRAWUPDATE);
2208 set(obj, MUIA_TextIconList_Width, data->width);
2210 else if (new_colwidth < act_colwidth)
2212 BOOL scroll_left = FALSE;
2214 data->column_width[data->click_column] = new_colwidth;
2215 data->width += new_colwidth - act_colwidth;
2217 if (data->view_x + data->view_width > data->width)
2219 LONG new_view_x = data->width - data->view_width;
2221 if (new_view_x < 0) new_view_x = 0;
2222 if (new_view_x != data->view_x)
2224 scroll_left = TRUE;
2225 data->view_x = new_view_x;
2229 data->update = UPDATE_ALL;
2230 MUI_Redraw(obj, MADF_DRAWUPDATE);
2232 SetAttrs(obj, scroll_left ? MUIA_TextIconList_Left : TAG_IGNORE, data->view_x,
2233 MUIA_TextIconList_Width, data->width,
2234 TAG_DONE);
2236 } /* else if (new_colwidth < act_colwidth) */
2238 } /* else if (data->inputstate == INPUTSTATE_COL_RESIZE) */
2239 else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK)
2241 BOOL old = ColumnHeaderUnderMouse(data, data->click_x, data->click_y);
2242 BOOL new = ColumnHeaderUnderMouse(data, mx, my);
2244 if (new != old)
2246 data->click_x = mx;
2247 data->click_y = my;
2248 data->update = UPDATE_HEADER;
2249 MUI_Redraw(obj, MADF_DRAWUPDATE);
2252 else if (data->inputstate == INPUTSTATE_LASSO)
2254 struct Rectangle old_lasso, new_lasso;
2255 struct Region *region;
2256 APTR clip;
2258 data->click_x = mx;
2259 data->click_y = my;
2261 data->old_lasso_rect = data->lasso_rect;
2262 GetAbsoluteLassoRect(data, &old_lasso);
2263 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
2264 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
2265 GetAbsoluteLassoRect(data, &new_lasso);
2267 region = NewRectRegion(new_lasso.MinX, new_lasso.MinY, new_lasso.MaxX, new_lasso.MaxY);
2268 if (region)
2270 struct Rectangle render_range;
2272 XorRectRegion(region, &old_lasso);
2273 OrRectOutlineRegion(region, &old_lasso);
2274 OrRectOutlineRegion(region, &new_lasso);
2276 render_range = region->bounds;
2278 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
2280 data->update = UPDATE_ALL;
2281 data->update_rect1 = &render_range;
2282 MUI_Redraw(obj, MADF_DRAWUPDATE);
2283 data->update_rect1 = 0;
2285 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
2288 RethinkLasso(obj, data);
2290 if ((mx >= data->view_rect.MinX) &&
2291 (my >= data->view_rect.MinY) &&
2292 (mx <= data->view_rect.MaxX) &&
2293 (my <= data->view_rect.MaxY))
2295 DisableAutoScrollTimer(obj, data);
2297 else
2299 EnableAutoScrollTimer(obj, data);
2304 break;
2306 } /* switch (msg->imsg->Class) */
2308 } /* if (msg->imsg) */
2310 return retval;
2314 /**************************************************************************
2315 MUIM_TextIconList_Clear
2316 **************************************************************************/
2317 static IPTR TextIconList_Clear(struct IClass *cl, Object *obj, struct MUIP_TextIconList_Clear *msg)
2319 struct TextIconList_DATA *data = INST_DATA(cl, obj);
2320 struct TextIconEntry *node;
2321 LONG i;
2323 while ((node = (struct TextIconEntry *)RemTail((struct List *)&data->entries_list)))
2325 FreePooled(data->pool,node,sizeof(*node));
2327 NewList((struct List *)&data->selection_list);
2329 data->view_x = data->view_y = data->width = data->height = 0;
2330 data->num_entries = 0;
2331 data->active_entry = -1;
2332 data->num_selected = 0;
2335 for(i = 0; i < NUM_COLUMNS; i++)
2337 data->column_maxwidth[i] = 0;
2340 SetAttrs(obj, MUIA_TextIconList_Left, data->view_x,
2341 MUIA_TextIconList_Top, data->view_y,
2342 MUIA_TextIconList_Width, data->width,
2343 MUIA_TextIconList_Height, data->height,
2344 TAG_DONE);
2346 data->update = UPDATE_ALL;
2347 MUI_Redraw(obj,MADF_DRAWUPDATE);
2348 return 1;
2351 /**************************************************************************
2352 MUIM_TextIconList_Add.
2353 Returns 0 on failure otherwise 1
2354 **************************************************************************/
2355 static IPTR TextIconList_Add(struct IClass *cl, Object *obj, struct MUIP_TextIconList_Add *msg)
2357 struct TextIconList_DATA *data = INST_DATA(cl, obj);
2358 struct TextIconEntry *entry;
2359 struct DateTime dt;
2360 UBYTE *sp;
2362 if (!(entry = AllocPooled(data->pool,sizeof(struct TextIconEntry))))
2364 return 0;
2367 memset(entry, 0, sizeof(struct TextIconEntry));
2369 entry->fib = *msg->fib;
2371 if (entry->fib.fib_DirEntryType > 0)
2373 strcpy(GetTextIconEntryText(data, entry, INDEX_SIZE), "Drawer");
2375 else
2377 sprintf(GetTextIconEntryText(data, entry, INDEX_SIZE), "%ld", entry->fib.fib_Size);
2380 dt.dat_Stamp = entry->fib.fib_Date;
2381 dt.dat_Format = FORMAT_DOS;
2382 dt.dat_Flags = 0;
2383 dt.dat_StrDay = NULL;
2384 dt.dat_StrDate = GetTextIconEntryText(data, entry, INDEX_DATE);
2385 dt.dat_StrTime = GetTextIconEntryText(data, entry, INDEX_TIME);;
2387 DateToStr(&dt);
2389 sp = GetTextIconEntryText(data, entry, INDEX_PROTECTION);
2390 *sp++ = (entry->fib.fib_Protection & FIBF_SCRIPT) ? 's' : '-';
2391 *sp++ = (entry->fib.fib_Protection & FIBF_PURE) ? 'p' : '-';
2392 *sp++ = (entry->fib.fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
2393 *sp++ = (entry->fib.fib_Protection & FIBF_READ) ? '-' : 'r';
2394 *sp++ = (entry->fib.fib_Protection & FIBF_WRITE) ? '-' : 'w';
2395 *sp++ = (entry->fib.fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
2396 *sp++ = (entry->fib.fib_Protection & FIBF_DELETE) ? '-' : 'd';
2397 *sp++ = '\0';
2399 data->num_entries++;
2401 SortInNode(data, (struct List *)&data->entries_list, (struct Node *)entry, (APTR)CompareNodes);
2403 if (data->is_setup)
2405 CalcEntryDimension(data, entry);
2406 data->height += data->lineheight;
2408 CalcWidth(data);
2410 SetAttrs(obj, MUIA_TextIconList_Width, data->width,
2411 MUIA_TextIconList_Height, data->height,
2412 TAG_DONE);
2415 return 1;
2418 BOOPSI_DISPATCHER(IPTR,TextIconList_Dispatcher, cl, obj, msg)
2420 switch (msg->MethodID)
2423 case OM_NEW: return TextIconList_New(cl, obj, (struct opSet *)msg);
2424 case OM_DISPOSE: return TextIconList_Dispose(cl,obj, msg);
2425 case OM_SET: return TextIconList_Set(cl,obj,(struct opSet *)msg);
2426 case OM_GET: return TextIconList_Get(cl,obj,(struct opGet *)msg);
2427 case MUIM_Setup: return TextIconList_Setup(cl,obj,(struct MUIP_Setup *)msg);
2428 case MUIM_Show: return TextIconList_Show(cl,obj,(struct MUIP_Show *)msg);
2429 case MUIM_Hide: return TextIconList_Hide(cl,obj,(struct MUIP_Hide *)msg);
2430 case MUIM_Cleanup: return TextIconList_Cleanup(cl,obj,(struct MUIP_Cleanup *)msg);
2431 case MUIM_AskMinMax: return TextIconList_AskMinMax(cl,obj,(struct MUIP_AskMinMax *)msg);
2432 case MUIM_Draw: return TextIconList_Draw(cl,obj,(struct MUIP_Draw *)msg);
2433 // case MUIM_Layout: return TextIconList_Layout(cl,obj,(struct MUIP_Layout *)msg);
2434 case MUIM_HandleEvent: return TextIconList_HandleEvent(cl,obj,(struct MUIP_HandleEvent *)msg);
2435 // case MUIM_CreateDragImage: return TextIconList_CreateDragImage(cl,obj,(APTR)msg);
2436 // case MUIM_DeleteDragImage: return TextIconList_DeleteDragImage(cl,obj,(APTR)msg);
2437 // case MUIM_DragQuery: return TextIconList_DragQuery(cl,obj,(APTR)msg);
2438 // case MUIM_DragReport: return TextIconList_DragReport(cl,obj,(APTR)msg);
2439 // case MUIM_DragDrop: return TextIconList_DragDrop(cl,obj,(APTR)msg);
2441 // case MUIM_TextIconList_Update: return TextIconList_Update(cl,obj,(APTR)msg);
2442 case MUIM_TextIconList_Clear: return TextIconList_Clear(cl,obj,(APTR)msg);
2443 case MUIM_TextIconList_Add: return TextIconList_Add(cl,obj,(APTR)msg);
2444 // case MUIM_TextIconList_NextSelected: return TextIconList_NextSelected(cl,obj,(APTR)msg);
2445 // case MUIM_TextIconList_UnselectAll: return TextIconList_UnselectAll(cl,obj,(APTR)msg);
2447 case MUIM_TextIconList_AutoScroll: return TextIconList_AutoScroll(cl,obj,(APTR)msg);
2450 return DoSuperMethodA(cl, obj, msg);
2452 BOOPSI_DISPATCHER_END
2454 /*================ TextIconListview class ===================*/
2456 #define MUIB_TextIconListview (MUIB_AROS | 0x00000800)
2458 #define MUIA_TextIconListview_TextIconList (MUIB_TextIconListview | 0x00000000)
2459 #define MUIA_TextIconListview_UseWinBorder (MUIB_TextIconListview | 0x00000001)
2461 #define TextIconListviewObject BOOPSIOBJMACRO_START(CL_TextIconListview->mcc_Class)
2463 struct TextIconListview_DATA
2465 Object *texticonlist;
2466 Object *vert, *horiz, *button;
2467 struct Hook hook;
2468 struct Hook layout_hook;
2472 IPTR TextIconListview_Layout_Function(struct Hook *hook, Object *obj, struct MUI_LayoutMsg *lm)
2474 struct TextIconListview_DATA *data = (struct TextIconListview_DATA *)hook->h_Data;
2476 switch (lm->lm_Type)
2478 case MUILM_MINMAX:
2480 /* Calulate the minmax dimension of the group,
2481 ** We only have a fixed number of children, so we need no NextObject()
2483 WORD maxxxxwidth = 0;
2484 WORD maxxxxheight = 0;
2486 maxxxxwidth = _minwidth(data->texticonlist) + _minwidth(data->vert);
2487 if (_minwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _minwidth(data->horiz);
2488 lm->lm_MinMax.MinWidth = maxxxxwidth;
2490 maxxxxheight = _minheight(data->texticonlist) + _minheight(data->horiz);
2491 if (_minheight(data->vert) > maxxxxheight) maxxxxheight = _minheight(data->vert);
2492 lm->lm_MinMax.MinHeight = maxxxxheight;
2494 maxxxxwidth = _defwidth(data->texticonlist) + _defwidth(data->vert);
2495 if (_defwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _defwidth(data->horiz);
2496 lm->lm_MinMax.DefWidth = maxxxxwidth;
2498 maxxxxheight = _defheight(data->texticonlist) + _defheight(data->horiz);
2499 if (_defheight(data->vert) > maxxxxheight) maxxxxheight = _defheight(data->vert);
2500 lm->lm_MinMax.DefHeight = maxxxxheight;
2502 lm->lm_MinMax.MaxWidth = MUI_MAXMAX;
2503 lm->lm_MinMax.MaxHeight = MUI_MAXMAX;
2505 return 0;
2508 case MUILM_LAYOUT:
2510 /* Now place the objects between (0,0,lm->lm_Layout.Width-1,lm->lm_Layout.Height-1)
2513 LONG virt_width;
2514 LONG virt_height;
2515 LONG vert_width = _minwidth(data->vert);
2516 LONG horiz_height = _minheight(data->horiz);
2517 LONG lay_width = lm->lm_Layout.Width;
2518 LONG lay_height = lm->lm_Layout.Height;
2519 LONG cont_width;
2520 LONG cont_height;
2522 /* layout the virtual group a first time, to determine the virtual width/height */
2523 MUI_Layout(data->texticonlist,0,0,lay_width,lay_height,0);
2525 get(data->texticonlist, MUIA_TextIconList_Width, &virt_width);
2526 get(data->texticonlist, MUIA_TextIconList_Height, &virt_height);
2528 virt_width += _subwidth(data->texticonlist);
2529 virt_height += _subheight(data->texticonlist);
2531 if (virt_width > lay_width && virt_height > lay_height)
2533 /* We need all scrollbars and the button */
2534 set(data->vert, MUIA_ShowMe, TRUE); /* We could also overload MUIM_Show... */
2535 set(data->horiz, MUIA_ShowMe, TRUE);
2536 set(data->button, MUIA_ShowMe, TRUE);
2537 cont_width = lay_width - vert_width;
2538 cont_height = lay_height - horiz_height;
2539 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
2540 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
2541 MUI_Layout(data->button, cont_width, cont_height, vert_width, horiz_height, 0);
2542 } else
2544 if (virt_height > lay_height)
2546 set(data->vert, MUIA_ShowMe, TRUE);
2547 set(data->horiz, MUIA_ShowMe, FALSE);
2548 set(data->button, MUIA_ShowMe, FALSE);
2550 cont_width = lay_width - vert_width;
2551 cont_height = lay_height;
2552 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
2553 } else
2555 if (virt_width > lay_width)
2557 set(data->vert, MUIA_ShowMe, FALSE);
2558 set(data->horiz, MUIA_ShowMe, TRUE);
2559 set(data->button, MUIA_ShowMe, FALSE);
2561 cont_width = lay_width;
2562 cont_height = lay_height - horiz_height;
2563 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
2564 } else
2566 set(data->vert, MUIA_ShowMe, FALSE);
2567 set(data->horiz, MUIA_ShowMe, FALSE);
2568 set(data->button, MUIA_ShowMe, FALSE);
2570 cont_width = lay_width;
2571 cont_height = lay_height;
2576 /* Layout the group a second time, note that setting _mwidth() and _mheight() should be enough, or we invent a new flag */
2577 MUI_Layout(data->texticonlist,0,0,cont_width,cont_height,0);
2578 return 1;
2581 return 0;
2585 IPTR TextIconListview_Function(struct Hook *hook, APTR dummyobj, void **msg)
2587 struct TextIconListview_DATA *data = (struct TextIconListview_DATA *)hook->h_Data;
2588 int type = (int)msg[0];
2589 LONG val = (LONG)msg[1];
2591 switch (type)
2593 case 1:
2595 get(data->vert,MUIA_Prop_First,&val);
2596 SetAttrs(data->texticonlist,MUIA_TextIconList_Top, val, MUIA_NoNotify, TRUE, TAG_DONE);
2597 break;
2600 case 2:
2602 get(data->horiz,MUIA_Prop_First,&val);
2603 SetAttrs(data->texticonlist,MUIA_TextIconList_Left, val, MUIA_NoNotify, TRUE, TAG_DONE);
2604 break;
2606 case 3: nnset(data->horiz, MUIA_Prop_First, val); break;
2607 case 4: nnset(data->vert, MUIA_Prop_First, val); break;
2609 return 0;
2613 IPTR TextIconListview__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2615 struct TextIconListview_DATA *data;
2616 //struct TagItem *tags,*tag;
2617 Object *texticonlist = (Object*)GetTagData(MUIA_TextIconListview_TextIconList, 0, msg->ops_AttrList);
2618 Object *vert,*horiz,*button,*group;
2620 int usewinborder;
2622 usewinborder = GetTagData(MUIA_TextIconListview_UseWinBorder, FALSE, msg->ops_AttrList);
2624 if (!usewinborder) button = ScrollbuttonObject, End;
2625 else button = NULL;
2627 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
2628 MUIA_Group_Horiz, FALSE,
2629 Child, (IPTR) (group = GroupObject,
2630 Child, (IPTR) texticonlist,
2631 Child, (IPTR) (vert = ScrollbarObject,
2632 usewinborder ? MUIA_Prop_UseWinBorder : TAG_IGNORE, MUIV_Prop_UseWinBorder_Right,
2633 MUIA_Prop_DeltaFactor, 20,
2634 MUIA_Group_Horiz, FALSE,
2635 End),
2636 Child, (IPTR) (horiz = ScrollbarObject,
2637 usewinborder?MUIA_Prop_UseWinBorder:TAG_IGNORE, MUIV_Prop_UseWinBorder_Bottom,
2638 MUIA_Prop_DeltaFactor, 20,
2639 MUIA_Group_Horiz, TRUE,
2640 End),
2641 usewinborder ? TAG_IGNORE : Child, (IPTR) button,
2642 End),
2643 TAG_DONE);
2645 if (!obj)
2647 return 0;
2650 data = INST_DATA(cl, obj);
2651 data->vert = vert;
2652 data->horiz = horiz;
2653 data->button = button;
2654 data->texticonlist = texticonlist;
2656 if (!usewinborder)
2658 data->layout_hook.h_Entry = HookEntry;
2659 data->layout_hook.h_SubEntry = (HOOKFUNC)TextIconListview_Layout_Function;
2660 data->layout_hook.h_Data = data;
2662 SetAttrs(group, MUIA_Group_Forward, FALSE,
2663 MUIA_Group_LayoutHook, (IPTR) &data->layout_hook,
2664 TAG_DONE);
2667 data->hook.h_Entry = HookEntry;
2668 data->hook.h_SubEntry = (HOOKFUNC)TextIconListview_Function;
2669 data->hook.h_Data = data;
2671 DoMethod(vert, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 1, MUIV_TriggerValue);
2672 DoMethod(horiz, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 2, MUIV_TriggerValue);
2673 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Left, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 3, MUIV_TriggerValue);
2674 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Top, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 4, MUIV_TriggerValue);
2675 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Width, MUIV_EveryTime, (IPTR)horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
2676 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Height, MUIV_EveryTime, (IPTR)vert, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
2677 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_VisWidth, MUIV_EveryTime, (IPTR)horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
2678 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_VisHeight, MUIV_EveryTime, (IPTR)vert, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
2680 return (IPTR)obj;
2684 IPTR TextIconListview__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2686 //struct TextIconListview_DATA *data = INST_DATA(cl, obj);
2688 return DoSuperMethodA(cl,obj,msg);
2691 IPTR TextIconListview__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
2693 struct TextIconListview_DATA *data = INST_DATA(cl, obj);
2694 IPTR top,left,width,height,viswidth,visheight;
2696 get(data->texticonlist, MUIA_TextIconList_Left, &left);
2697 get(data->texticonlist, MUIA_TextIconList_Top, &top);
2698 get(data->texticonlist, MUIA_TextIconList_Width, &width);
2699 get(data->texticonlist, MUIA_TextIconList_Height, &height);
2700 get(data->texticonlist, MUIA_TextIconList_VisWidth, &viswidth);
2701 get(data->texticonlist, MUIA_TextIconList_VisHeight, &visheight);
2703 SetAttrs(data->horiz, MUIA_Prop_First, left,
2704 MUIA_Prop_Entries, width,
2705 MUIA_Prop_Visible, viswidth,
2706 TAG_DONE);
2709 SetAttrs(data->vert, MUIA_Prop_First, top,
2710 MUIA_Prop_Entries, height,
2711 MUIA_Prop_Visible, visheight,
2712 TAG_DONE);
2714 return DoSuperMethodA(cl,obj,(Msg)msg);
2717 BOOPSI_DISPATCHER(IPTR,TextIconListview_Dispatcher, cl, obj, msg)
2719 switch (msg->MethodID)
2721 case OM_NEW: return TextIconListview__OM_NEW(cl, obj, (struct opSet *) msg);
2722 case OM_DISPOSE: return TextIconListview__OM_DISPOSE(cl, obj, msg);
2723 case MUIM_Show: return TextIconListview__MUIM_Show(cl, obj, (struct MUIP_Show*)msg);
2726 return DoSuperMethodA(cl, obj, msg);
2729 BOOPSI_DISPATCHER_END
2732 int main(void)
2734 Object *wnd, *texticonlist;
2735 #if 0
2736 Object *iconlist;
2737 #endif
2739 MUIMasterBase = (struct Library*)OpenLibrary("muimaster.library",0);
2741 CL_TextIconListview = MUI_CreateCustomClass(NULL,MUIC_Group,NULL,sizeof(struct TextIconListview_DATA), TextIconListview_Dispatcher);
2742 CL_TextIconList = MUI_CreateCustomClass(NULL,MUIC_Area,NULL,sizeof(struct TextIconList_DATA), TextIconList_Dispatcher);
2744 app = ApplicationObject,
2745 SubWindow, (IPTR) (wnd = WindowObject,
2746 MUIA_Window_Title, (IPTR) "texticonlist",
2747 MUIA_Window_Activate, TRUE,
2749 WindowContents, (IPTR) VGroup,
2750 MUIA_Background, MUII_GroupBack,
2751 #if 0
2752 Child, (IPTR) IconListviewObject,
2753 MUIA_IconListview_IconList, (IPTR) (iconlist = IconDrawerListObject,
2754 InputListFrame,
2755 MUIA_IconDrawerList_Drawer, (IPTR) "C:",
2756 End),
2757 End,
2758 #endif
2759 Child, (IPTR) TextIconListviewObject,
2760 // MUIA_TextIconListview_UseWinBorder, TRUE,
2761 MUIA_TextIconListview_TextIconList, (IPTR) (texticonlist = TextIconListObject,
2762 InputListFrame,
2763 InnerSpacing(0,0),
2764 End),
2765 End,
2768 Child, (IPTR) (texticonlist = TextIconListObject, InputListFrame, End),
2770 End,
2771 End),
2772 End;
2774 if (app)
2776 ULONG sigs = 0;
2778 DoMethod
2780 wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, (IPTR) app,
2781 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit
2785 BPTR lock = Lock("C:", SHARED_LOCK);
2787 if (lock)
2789 struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, NULL);
2790 if (fib)
2792 if (Examine(lock, fib))
2794 while(ExNext(lock, fib))
2796 DoMethod(texticonlist, MUIM_TextIconList_Add, (IPTR) fib);
2800 FreeDosObject(DOS_FIB, fib);
2803 UnLock(lock);
2807 set(wnd,MUIA_Window_Open,TRUE);
2808 #if 0
2809 set(iconlist, MUIA_IconDrawerList_Drawer, "C:");
2810 #endif
2812 while (DoMethod(app, MUIM_Application_NewInput, (IPTR) &sigs) != MUIV_Application_ReturnID_Quit)
2814 if (sigs)
2816 sigs = Wait(sigs | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
2817 if (sigs & SIGBREAKF_CTRL_C) break;
2818 if (sigs & SIGBREAKF_CTRL_D) break;
2822 MUI_DisposeObject(app);
2825 MUI_DeleteCustomClass(CL_TextIconList);
2826 MUI_DeleteCustomClass(CL_TextIconListview);
2828 CloseLibrary(MUIMasterBase);
2830 return 0;