closing brace is only needed on smp build.
[AROS.git] / test / Zune / texticonlist.c
blobc790cff5de605c340044bd8975bf7d330b99f4d3
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 = 0, x2 = 0;
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;
1253 struct TagItem *tags;
1254 LONG oldleft = data->view_x, oldtop = data->view_y;
1256 /* parse initial taglist */
1257 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
1259 switch (tag->ti_Tag)
1261 case MUIA_TextIconList_Left:
1262 if (data->view_x != (LONG)tag->ti_Data)
1264 LONG new_view_x = (LONG)tag->ti_Data;
1266 if (new_view_x + data->view_width > data->width)
1268 new_view_x = data->width - data->view_width;
1270 if (new_view_x < 0) new_view_x = 0;
1272 data->view_x = new_view_x;
1273 tag->ti_Data = new_view_x;
1275 break;
1277 case MUIA_TextIconList_Top:
1278 if (data->view_y != (LONG)tag->ti_Data)
1280 LONG new_view_y = (LONG)tag->ti_Data;
1282 if (new_view_y + data->view_height > data->height)
1284 new_view_y = data->height - data->view_height;
1286 if (new_view_y < 0) new_view_y = 0;
1288 data->view_y = new_view_y;
1289 tag->ti_Data = new_view_y;
1291 break;
1295 if ((oldleft != data->view_x) || (oldtop != data->view_y))
1297 data->update = UPDATE_SCROLL;
1298 data->update_scrolldx = data->view_x - oldleft;
1299 data->update_scrolldy = data->view_y - oldtop;
1301 MUI_Redraw(obj, MADF_DRAWUPDATE);
1304 return DoSuperMethodA(cl, obj, (Msg)msg);
1307 /**************************************************************************
1308 OM_GET
1309 **************************************************************************/
1310 static IPTR TextIconList_Get(struct IClass *cl, Object *obj, struct opGet *msg)
1312 /* small macro to simplify return value storage */
1313 #define STORE *(msg->opg_Storage)
1314 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1316 switch (msg->opg_AttrID)
1318 case MUIA_TextIconList_Left: STORE = data->view_x; return 1;
1319 case MUIA_TextIconList_Top: STORE = data->view_y; return 1;
1320 case MUIA_TextIconList_Width: STORE = data->width; return 1;
1321 case MUIA_TextIconList_Height: STORE = data->height; return 1;
1324 return DoSuperMethodA(cl, obj, (Msg) msg);
1325 #undef STORE
1328 /**************************************************************************
1329 MUIM_Setup
1330 **************************************************************************/
1331 static IPTR TextIconList_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
1333 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1334 LONG i;
1336 if (!DoSuperMethodA(cl, obj, (Msg) msg)) return 0;
1338 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1340 InitRastPort(&data->temprp);
1341 SetFont(&data->temprp, _font(obj));
1342 data->truecolor = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH) >= 15;
1344 data->lineheight = LINE_EXTRAHEIGHT + _font(obj)->tf_YSize;
1345 data->is_setup = TRUE;
1347 for(i = 0; i < NUM_COLORS; i++)
1349 data->colors[i].rgbpixel = rgb_colors[i];
1350 data->colors[i].pixel = data->colors[i].rgbpixel;
1352 if (!data->truecolor || !CyberGfxBase)
1354 ULONG r = (rgb_colors[i] & 0x00FF0000) >> 16;
1355 ULONG g = (rgb_colors[i] & 0x0000FF00) >> 8;
1356 ULONG b = (rgb_colors[i] & 0x000000FF);
1358 LONG pen = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,
1359 r * 0x01010101,
1360 g * 0x01010101,
1361 b * 0x01010101,
1362 OBP_FailIfBad, FALSE,
1363 OBP_Precision, PRECISION_GUI,
1364 TAG_DONE);
1366 if (pen >= 0)
1368 data->colors[i].pixel = pen;
1369 data->colors[i].alloced = TRUE;
1371 else
1373 data->colors[i].pixel = _pens(obj)[pen_colors[i]];
1374 data->colors[i].alloced = FALSE;
1379 if (data->show_header)
1381 data->headerheight = HEADERLINE_EXTRAHEIGHT + _font(obj)->tf_YSize;
1383 else
1385 data->headerheight = 0;
1388 if (data->num_entries)
1390 CalcAllEntryDimensions(data);
1391 CalcWidth(data);
1392 data->height = data->num_entries * data->lineheight;
1393 RecalcColumnMaxWidths(data);
1395 SetAttrs(obj, MUIA_TextIconList_Width, data->width,
1396 MUIA_TextIconList_Height, data->height,
1397 TAG_DONE);
1400 return 1;
1403 /**************************************************************************
1404 MUIM_Show
1405 **************************************************************************/
1406 static IPTR TextIconList_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
1408 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1409 LONG newleft, newtop;
1410 IPTR rc;
1412 rc = DoSuperMethodA(cl, obj, (Msg)msg);
1414 newleft = data->view_x;
1415 newtop = data->view_y;
1417 data->view_width = _mwidth(obj);
1418 data->view_height = _mheight(obj) - data->headerheight;
1420 SetAttrs(obj, MUIA_TextIconList_VisWidth, data->view_width,
1421 MUIA_TextIconList_VisHeight, data->view_height,
1422 TAG_DONE);
1424 data->view_rect.MinX = _mleft(obj);
1425 data->view_rect.MinY = _mtop(obj) + data->headerheight;
1426 data->view_rect.MaxX = _mright(obj);
1427 data->view_rect.MaxY = _mbottom(obj);
1429 data->header_rect.MinX = _mleft(obj);
1430 data->header_rect.MinY = _mtop(obj);
1431 data->header_rect.MaxX = _mright(obj);
1432 data->header_rect.MaxY = _mtop(obj) + data->headerheight - 1;
1434 if (newleft + data->view_width > data->width) newleft = data->width - data->view_width;
1435 if (newleft < 0) newleft = 0;
1437 if (newtop + data->view_height > data->height) newtop = data->height - data->view_height;
1438 if (newtop < 0) newtop = 0;
1440 if ((newleft != data->view_x) || (newtop != data->view_y))
1442 SetAttrs(obj, MUIA_TextIconList_Left, newleft,
1443 MUIA_TextIconList_Top, newtop,
1444 TAG_DONE);
1447 SetFont(_rp(obj), _font(obj));
1449 data->is_shown = TRUE;
1451 return rc;
1454 /**************************************************************************
1455 MUIM_Hide
1456 **************************************************************************/
1457 static IPTR TextIconList_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
1459 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1460 IPTR rc;
1462 data->is_shown = FALSE;
1464 rc = DoSuperMethodA(cl, obj, (Msg)msg);
1466 return rc;
1469 /**************************************************************************
1470 MUIM_Cleanup
1471 **************************************************************************/
1472 static IPTR TextIconList_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
1474 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1475 LONG i;
1477 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1479 for(i = 0; i < NUM_COLORS; i++)
1481 if (data->colors[i].alloced)
1483 ReleasePen(_screen(obj)->ViewPort.ColorMap, data->colors[i].pixel);
1484 data->colors[i].alloced = FALSE;
1488 data->is_setup = FALSE;
1490 return DoSuperMethodA(cl, obj, (Msg) msg);
1493 /**************************************************************************
1494 MUIM_AskMinMax
1495 **************************************************************************/
1496 static IPTR TextIconList_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
1498 ULONG rc = DoSuperMethodA(cl, obj, (Msg) msg);
1500 msg->MinMaxInfo->MinWidth += 10;
1501 msg->MinMaxInfo->MinHeight += 10;
1503 msg->MinMaxInfo->DefWidth += 100;
1504 msg->MinMaxInfo->DefHeight += 100;
1506 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
1507 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
1509 return rc;
1512 static void DrawHeaderLine(Object *obj, struct TextIconList_DATA *data)
1514 APTR clip;
1516 if (data->show_header && MustRenderRect(data, &data->header_rect))
1518 clip = MUI_AddClipping(muiRenderInfo(obj), data->header_rect.MinX,
1519 data->header_rect.MinY,
1520 data->header_rect.MaxX - data->header_rect.MinX + 1,
1521 data->header_rect.MaxY - data->header_rect.MinY + 1);
1523 RenderHeaderline(obj, data);
1525 MUI_RemoveClipping(muiRenderInfo(obj),clip);
1529 static void DrawLassoOutline(Object *obj, struct TextIconList_DATA *data)
1531 struct Rectangle lasso;
1533 GetAbsoluteLassoRect(data, &lasso);
1535 #if 1
1536 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MinY, lasso.MaxX, lasso.MinY, COLOR_SELECTED_BACKGROUND);
1537 MyRectFill(data, _rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1538 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1539 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MinY, lasso.MinX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1540 #else
1541 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_SHADOW], 0, JAM1);
1542 Move(_rp(obj), lasso.MinX, lasso.MinY);
1543 Draw(_rp(obj), lasso.MaxX, lasso.MinY);
1544 Draw(_rp(obj), lasso.MaxX, lasso.MaxY);
1545 Draw(_rp(obj), lasso.MinX, lasso.MaxY);
1546 Draw(_rp(obj), lasso.MinX, lasso.MinY);
1547 #endif
1550 /**************************************************************************
1551 MUIM_Draw
1552 **************************************************************************/
1553 static IPTR TextIconList_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
1555 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1556 APTR clip;
1557 struct TextIconEntry *entry;
1559 DoSuperMethodA(cl, obj, (Msg) msg);
1561 if (msg->flags & MADF_DRAWUPDATE)
1563 if (data->update == UPDATE_SCROLL)
1565 struct Region *region;
1566 struct Rectangle xrect, yrect;
1567 BOOL scroll_caused_damage;
1569 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
1571 data->update = 0;
1573 if ((abs(data->update_scrolldx) >= data->view_width) ||
1574 (abs(data->update_scrolldy) >= data->view_height))
1576 data->update = UPDATE_ALL;
1577 MUI_Redraw(obj, MADF_DRAWUPDATE);
1578 return 0;
1581 region = NewRegion();
1582 if (!region)
1584 data->update = UPDATE_ALL;
1585 MUI_Redraw(obj, MADF_DRAWUPDATE);
1586 return 0;
1589 if (data->update_scrolldx > 0)
1591 xrect.MinX = data->view_rect.MaxX - data->update_scrolldx;
1592 xrect.MinY = data->view_rect.MinY;
1593 xrect.MaxX = data->view_rect.MaxX;
1594 xrect.MaxY = data->view_rect.MaxY;
1596 OrRectRegion(region, &xrect);
1598 data->update_rect1 = &xrect;
1600 else if (data->update_scrolldx < 0)
1602 xrect.MinX = data->view_rect.MinX;
1603 xrect.MinY = data->view_rect.MinY;
1604 xrect.MaxX = data->view_rect.MinX - data->update_scrolldx;
1605 xrect.MaxY = data->view_rect.MaxY;
1607 OrRectRegion(region, &xrect);
1609 data->update_rect1 = &xrect;
1612 if (data->update_scrolldy > 0)
1614 yrect.MinX = data->view_rect.MinX;
1615 yrect.MinY = data->view_rect.MaxY - data->update_scrolldy;
1616 yrect.MaxX = data->view_rect.MaxX;
1617 yrect.MaxY = data->view_rect.MaxY;
1619 OrRectRegion(region, &yrect);
1621 data->update_rect2 = &yrect;
1623 else if (data->update_scrolldy < 0)
1625 yrect.MinX = data->view_rect.MinX;
1626 yrect.MinY = data->view_rect.MinY;
1627 yrect.MaxX = data->view_rect.MaxX;
1628 yrect.MaxY = data->view_rect.MinY - data->update_scrolldy;
1630 OrRectRegion(region, &yrect);
1632 data->update_rect2 = &yrect;
1635 ScrollRasterBF(_rp(obj),
1636 data->update_scrolldx,
1637 data->update_scrolldy,
1638 data->view_rect.MinX,
1639 data->view_rect.MinY,
1640 data->view_rect.MaxX,
1641 data->view_rect.MaxY);
1643 if (data->show_header && data->update_scrolldx)
1645 ScrollRasterBF(_rp(obj),
1646 data->update_scrolldx,
1648 data->header_rect.MinX,
1649 data->header_rect.MinY,
1650 data->header_rect.MaxX,
1651 data->header_rect.MaxY);
1654 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
1656 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1657 data->update = UPDATE_ALL;
1658 MUI_Redraw(obj, MADF_DRAWUPDATE);
1659 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1661 if (data->show_header && data->update_scrolldx)
1663 xrect.MinY = data->header_rect.MinY;
1664 xrect.MaxY = data->header_rect.MaxY;
1666 data->update_rect1 = &xrect;
1667 data->update_rect2 = NULL;
1669 clip = MUI_AddClipping(muiRenderInfo(obj), xrect.MinX,
1670 xrect.MinY,
1671 xrect.MaxX - xrect.MinX + 1,
1672 xrect.MaxY - xrect.MinY + 1);
1674 data->update = UPDATE_ALL;
1675 MUI_Redraw(obj, MADF_DRAWUPDATE);
1676 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1678 data->update_rect2 = NULL;
1682 data->update_rect1 = data->update_rect2 = NULL;
1683 data->update_scrolldx = data->update_scrolldy = 0;
1685 // DisposeRegion(region);
1687 if (scroll_caused_damage)
1689 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
1691 /* Theoretically it might happen that more damage is caused
1692 after ScrollRaster. By something else, like window movement
1693 in front of our window. Therefore refresh root object of
1694 window, not just this object */
1696 Object *o = NULL;
1698 get(_win(obj),MUIA_Window_RootObject, &o);
1699 MUI_Redraw(o, MADF_DRAWOBJECT);
1701 MUI_EndRefresh(muiRenderInfo(obj), 0);
1705 return 0;
1707 } /* if (data->update == UPDATE_SCROLL) */
1708 else if (data->update == UPDATE_DIRTY_ENTRIES)
1710 struct Region *clipregion;
1711 LONG first, numvisible, index = 0;
1713 data->update = 0;
1715 clipregion = NewRectRegion(data->view_rect.MinX,
1716 data->view_rect.MinY,
1717 data->view_rect.MaxX,
1718 data->view_rect.MaxY);
1720 if (clipregion)
1722 if (data->lasso_active)
1724 struct Rectangle lasso_rect;
1726 GetAbsoluteLassoRect(data, &lasso_rect);
1727 ClearRectRegion(clipregion, &lasso_rect);
1730 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1732 first = FirstVisibleLine(data);
1733 numvisible = NumVisibleLines(data);
1735 ForeachNode(&data->entries_list, entry)
1737 if (entry->dirty)
1739 if ((index >= first) && (index < first + numvisible))
1741 RenderEntry(obj, data, index);
1744 index++;
1747 if (data->lasso_active)
1749 struct Rectangle lasso_rect;
1750 struct Rectangle vis_lasso_rect;
1752 GetAbsoluteLassoRect(data, &lasso_rect);
1754 if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect))
1756 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1758 clipregion = NewRectRegion(vis_lasso_rect.MinX,
1759 vis_lasso_rect.MinY,
1760 vis_lasso_rect.MaxX,
1761 vis_lasso_rect.MaxY);
1763 data->lasso_paint = TRUE;
1765 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1767 index = 0;
1768 ForeachNode(&data->entries_list, entry)
1770 if (entry->dirty)
1772 if ((index >= first) && (index < first + numvisible))
1774 RenderEntry(obj, data, index);
1777 index++;
1780 data->lasso_paint = FALSE;
1782 DrawLassoOutline(obj, data);
1784 } /* if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect)) */
1786 } /* if (data->lasso_active) */
1788 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1790 ForeachNode(&data->entries_list, entry)
1792 if (entry->dirty) entry->dirty = FALSE;
1794 return 0;
1797 } /* else if (data->update == UPDATE_DIRTY_ENTRIES) */
1798 else if (data->update == UPDATE_HEADER)
1800 data->update = 0;
1802 DrawHeaderLine(obj, data);
1804 return 0;
1807 } /* if (msg->flags & MADF_DRAWUPDATE) */
1809 if (MustRenderRect(data, &data->view_rect))
1811 struct Region *clipregion;
1813 clipregion = NewRectRegion(data->view_rect.MinX,
1814 data->view_rect.MinY,
1815 data->view_rect.MaxX,
1816 data->view_rect.MaxY);
1818 if (clipregion)
1820 if (data->lasso_active)
1822 struct Rectangle lasso_rect;
1824 GetAbsoluteLassoRect(data, &lasso_rect);
1825 ClearRectRegion(clipregion, &lasso_rect);
1828 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1830 RenderAllEntries(obj, data);
1832 if (data->lasso_active)
1834 struct Rectangle lasso_rect;
1835 struct Rectangle vis_lasso_rect;
1837 GetAbsoluteLassoRect(data, &lasso_rect);
1839 if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect))
1841 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1843 clipregion = NewRectRegion(vis_lasso_rect.MinX,
1844 vis_lasso_rect.MinY,
1845 vis_lasso_rect.MaxX,
1846 vis_lasso_rect.MaxY);
1848 data->lasso_paint = TRUE;
1850 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1852 RenderAllEntries(obj, data);
1854 data->lasso_paint = FALSE;
1856 DrawLassoOutline(obj, data);
1861 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1863 } /* if (clipregion) */
1865 } /* if (MustRenderRect(data, &data->view_rect)) */
1867 DrawHeaderLine(obj, data);
1869 data->update = 0;
1871 return 0;
1874 /**************************************************************************
1875 MUIM_Draw
1876 **************************************************************************/
1877 static IPTR TextIconList_AutoScroll(struct IClass *cl, Object *obj, Msg msg)
1879 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1881 if (data->lasso_active)
1883 LONG new_view_x, new_view_y;
1885 new_view_x = data->view_x;
1886 new_view_y = data->view_y;
1888 if (data->click_x < data->view_rect.MinX)
1890 new_view_x -= (data->view_rect.MinX - data->click_x) / 4;
1892 else if (data->click_x > data->view_rect.MaxX)
1894 new_view_x += (data->click_x - data->view_rect.MaxX) / 4;
1897 if (data->click_y < data->view_rect.MinY)
1899 new_view_y -= (data->view_rect.MinY - data->click_y) / 4;
1901 else if (data->click_y > data->view_rect.MaxY)
1903 new_view_y += (data->click_y - data->view_rect.MaxY) / 4;
1906 if (new_view_x + data->view_width > data->width)
1908 new_view_x = data->width - data->view_width;
1910 if (new_view_x < 0) new_view_x = 0;
1912 if (new_view_y + data->view_height > data->height)
1914 new_view_y = data->height - data->view_height;
1916 if (new_view_y < 0) new_view_y = 0;
1918 if ((new_view_x != data->view_x) || (new_view_y != data->view_y))
1920 data->old_lasso_rect = data->lasso_rect;
1922 data->lasso_rect.MaxX += new_view_x - data->view_x;
1923 data->lasso_rect.MaxY += new_view_y - data->view_y;
1925 RethinkLasso(obj, data);
1927 SetAttrs(obj, MUIA_TextIconList_Left, new_view_x,
1928 MUIA_TextIconList_Top, new_view_y,
1929 TAG_DONE);
1933 else
1935 DisableAutoScrollTimer(obj, data);
1938 return 0;
1941 /**************************************************************************
1942 MUIM_HandleEvent
1943 **************************************************************************/
1944 static IPTR TextIconList_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
1946 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1947 IPTR retval = 0;
1949 if (msg->imsg)
1951 LONG mx = msg->imsg->MouseX;
1952 LONG my = msg->imsg->MouseY;
1953 LONG line, col;
1954 BOOL shift_qual;
1956 shift_qual = (msg->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? TRUE : FALSE;
1958 switch (msg->imsg->Class)
1960 case IDCMP_MOUSEBUTTONS:
1961 switch(msg->imsg->Code)
1963 case SELECTDOWN:
1964 //kprintf("SELECTDOWN\n");
1965 if (data->inputstate == INPUTSTATE_NONE)
1967 if ( ((line = LineUnderMouse(data, mx, my)) >= 0) &&
1968 ((col = ColumnUnderMouse(data, mx, my)) >= 0) )
1970 //kprintf("click on line %d col %d\n", line, col);
1972 if (data->column_clickable[col])
1974 if (data->active_entry != line)
1976 struct TextIconEntry *old, *new;
1978 old = GetEntryFromIndex(data, data->active_entry);
1979 new = GetEntryFromIndex(data, line);
1981 data->active_entry = line;
1982 if (old && old->selected && !shift_qual)
1984 Remove((struct Node *)&old->selection_node);
1985 old->selected = FALSE;
1986 old->dirty = TRUE;
1988 data->num_selected--;
1991 if (!shift_qual && data->num_selected)
1993 struct TextIconEntry *entry;
1995 ForeachNode(&data->entries_list, entry)
1997 if (entry->selected)
1999 Remove((struct Node *)&entry->selection_node);
2000 entry->selected = FALSE;
2001 entry->dirty = TRUE;
2005 data->num_selected = 0;
2008 if (new && !new->selected)
2010 AddTail((struct List *)&data->selection_list, (struct Node *)&new->selection_node);
2011 new->selected = TRUE;
2012 new->dirty = TRUE;
2014 data->num_selected++;
2017 data->update = UPDATE_DIRTY_ENTRIES;
2018 MUI_Redraw(obj, MADF_DRAWUPDATE);
2020 } /* if (data->active_entry != line) */
2022 } /* if (data->column_clickable[col]) */
2023 else
2025 if (!shift_qual && data->num_selected)
2027 struct TextIconEntry *entry;
2029 ForeachNode(&data->entries_list, entry)
2031 if (entry->selected)
2033 Remove((struct Node *)&entry->selection_node);
2034 entry->selected = FALSE;
2035 entry->dirty = TRUE;
2039 data->num_selected = 0;
2040 data->update = UPDATE_DIRTY_ENTRIES;
2041 MUI_Redraw(obj, MADF_DRAWUPDATE);
2044 data->lasso_rect.MinX = mx - data->view_rect.MinX + data->view_x;
2045 data->lasso_rect.MinY = my - data->view_rect.MinY + data->view_y;
2046 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
2047 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
2049 data->inputstate = INPUTSTATE_LASSO;
2050 data->lasso_active = TRUE;
2052 data->click_x = mx;
2053 data->click_y = my;
2055 EnableMouseMoveEvents(obj, data);
2058 } /* if click on entry */
2059 else if ((col = ColumnResizeHandleUnderMouse(data, mx, my)) >= 0)
2061 data->inputstate = INPUTSTATE_COL_RESIZE;
2062 data->click_column = col;
2063 data->click_x = mx - data->column_width[col];
2065 EnableMouseMoveEvents(obj, data);
2067 } /* else if click on column header entry resize handle */
2068 else if ((col = ColumnHeaderUnderMouse(data, mx, my)) >= 0)
2070 data->inputstate = INPUTSTATE_COL_HEADER_CLICK;
2071 data->click_column = col;
2072 data->click_x = mx;
2073 data->click_y = my;
2075 EnableMouseMoveEvents(obj, data);
2077 data->update = UPDATE_HEADER;
2078 MUI_Redraw(obj, MADF_DRAWUPDATE);
2081 } /* if (data->inputstate == INPUTSTATE_NONE) */
2082 break;
2084 case SELECTUP:
2085 if (data->inputstate == INPUTSTATE_COL_RESIZE)
2087 DisableMouseMoveEvents(obj, data);
2089 data->inputstate = INPUTSTATE_NONE;
2091 else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK)
2093 DisableMouseMoveEvents(obj, data);
2095 data->inputstate = INPUTSTATE_NONE;
2097 if (ColumnHeaderUnderMouse(data, data->click_x, data->click_y) == data->click_column)
2100 if (data->column_sortable[data->click_column])
2102 if (data->sort_column == data->click_column)
2104 data->sort_direction = 1 - data->sort_direction;
2106 else
2108 data->sort_direction = SORT_DIRECTION_UP;
2109 data->sort_column = data->click_column;
2112 ReSortEntries(data);
2114 data->update = UPDATE_ALL;
2115 MUI_Redraw(obj, MADF_DRAWUPDATE);
2118 else
2120 data->update = UPDATE_HEADER;
2121 MUI_Redraw(obj, MADF_DRAWUPDATE);
2124 } /* mouse still over column header */
2126 } /* else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK) */
2127 else if (data->inputstate == INPUTSTATE_LASSO)
2129 DisableMouseMoveEvents(obj, data);
2130 DisableAutoScrollTimer(obj, data);
2132 data->inputstate = INPUTSTATE_NONE;
2133 data->lasso_active = FALSE;
2135 data->update = UPDATE_ALL;
2136 MUI_Redraw(obj, MADF_DRAWUPDATE);
2138 break;
2140 case MIDDLEDOWN:
2141 if (data->inputstate == INPUTSTATE_NONE)
2143 data->inputstate = INPUTSTATE_PAN;
2145 data->click_x = mx - data->view_rect.MinX + data->view_x;
2146 data->click_y = my - data->view_rect.MinY + data->view_y;
2148 EnableMouseMoveEvents(obj, data);
2151 break;
2153 case MIDDLEUP:
2154 if (data->inputstate == INPUTSTATE_PAN)
2156 DisableMouseMoveEvents(obj, data);
2158 data->inputstate = INPUTSTATE_NONE;
2160 break;
2162 } /* switch(msg->imsg->Code) */
2163 break;
2165 case IDCMP_MOUSEMOVE:
2166 if (data->inputstate == INPUTSTATE_PAN)
2168 LONG new_view_x, new_view_y;
2170 new_view_x = data->click_x - (mx - data->view_rect.MinX);
2171 new_view_y = data->click_y - (my - data->view_rect.MinY);
2173 if (new_view_x + data->view_width > data->width)
2175 new_view_x = data->width - data->view_width;
2177 if (new_view_x < 0) new_view_x = 0;
2179 if (new_view_y + data->view_height > data->height)
2181 new_view_y = data->height - data->view_height;
2183 if (new_view_y < 0) new_view_y = 0;
2185 if ((new_view_x != data->view_x) || (new_view_y != data->view_y))
2187 SetAttrs(obj, MUIA_TextIconList_Left, new_view_x,
2188 MUIA_TextIconList_Top, new_view_y,
2189 TAG_DONE);
2192 } /* if (data->inputstate == INPUTSTATE_PAN) */
2193 else if (data->inputstate == INPUTSTATE_COL_RESIZE)
2195 LONG act_colwidth = data->column_width[data->click_column];
2196 LONG new_colwidth = mx - data->click_x;
2198 if (new_colwidth < MIN_COLUMN_WIDTH) new_colwidth = MIN_COLUMN_WIDTH;
2200 if (new_colwidth > act_colwidth)
2202 data->column_width[data->click_column] = new_colwidth;
2203 data->width += new_colwidth - act_colwidth;
2204 data->update = UPDATE_ALL;
2205 MUI_Redraw(obj, MADF_DRAWUPDATE);
2207 set(obj, MUIA_TextIconList_Width, data->width);
2209 else if (new_colwidth < act_colwidth)
2211 BOOL scroll_left = FALSE;
2213 data->column_width[data->click_column] = new_colwidth;
2214 data->width += new_colwidth - act_colwidth;
2216 if (data->view_x + data->view_width > data->width)
2218 LONG new_view_x = data->width - data->view_width;
2220 if (new_view_x < 0) new_view_x = 0;
2221 if (new_view_x != data->view_x)
2223 scroll_left = TRUE;
2224 data->view_x = new_view_x;
2228 data->update = UPDATE_ALL;
2229 MUI_Redraw(obj, MADF_DRAWUPDATE);
2231 SetAttrs(obj, scroll_left ? MUIA_TextIconList_Left : TAG_IGNORE, data->view_x,
2232 MUIA_TextIconList_Width, data->width,
2233 TAG_DONE);
2235 } /* else if (new_colwidth < act_colwidth) */
2237 } /* else if (data->inputstate == INPUTSTATE_COL_RESIZE) */
2238 else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK)
2240 BOOL old = ColumnHeaderUnderMouse(data, data->click_x, data->click_y);
2241 BOOL new = ColumnHeaderUnderMouse(data, mx, my);
2243 if (new != old)
2245 data->click_x = mx;
2246 data->click_y = my;
2247 data->update = UPDATE_HEADER;
2248 MUI_Redraw(obj, MADF_DRAWUPDATE);
2251 else if (data->inputstate == INPUTSTATE_LASSO)
2253 struct Rectangle old_lasso, new_lasso;
2254 struct Region *region;
2255 APTR clip;
2257 data->click_x = mx;
2258 data->click_y = my;
2260 data->old_lasso_rect = data->lasso_rect;
2261 GetAbsoluteLassoRect(data, &old_lasso);
2262 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
2263 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
2264 GetAbsoluteLassoRect(data, &new_lasso);
2266 region = NewRectRegion(new_lasso.MinX, new_lasso.MinY, new_lasso.MaxX, new_lasso.MaxY);
2267 if (region)
2269 struct Rectangle render_range;
2271 XorRectRegion(region, &old_lasso);
2272 OrRectOutlineRegion(region, &old_lasso);
2273 OrRectOutlineRegion(region, &new_lasso);
2275 render_range = region->bounds;
2277 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
2279 data->update = UPDATE_ALL;
2280 data->update_rect1 = &render_range;
2281 MUI_Redraw(obj, MADF_DRAWUPDATE);
2282 data->update_rect1 = 0;
2284 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
2287 RethinkLasso(obj, data);
2289 if ((mx >= data->view_rect.MinX) &&
2290 (my >= data->view_rect.MinY) &&
2291 (mx <= data->view_rect.MaxX) &&
2292 (my <= data->view_rect.MaxY))
2294 DisableAutoScrollTimer(obj, data);
2296 else
2298 EnableAutoScrollTimer(obj, data);
2303 break;
2305 } /* switch (msg->imsg->Class) */
2307 } /* if (msg->imsg) */
2309 return retval;
2313 /**************************************************************************
2314 MUIM_TextIconList_Clear
2315 **************************************************************************/
2316 static IPTR TextIconList_Clear(struct IClass *cl, Object *obj, struct MUIP_TextIconList_Clear *msg)
2318 struct TextIconList_DATA *data = INST_DATA(cl, obj);
2319 struct TextIconEntry *node;
2320 LONG i;
2322 while ((node = (struct TextIconEntry *)RemTail((struct List *)&data->entries_list)))
2324 FreePooled(data->pool,node,sizeof(*node));
2326 NewList((struct List *)&data->selection_list);
2328 data->view_x = data->view_y = data->width = data->height = 0;
2329 data->num_entries = 0;
2330 data->active_entry = -1;
2331 data->num_selected = 0;
2334 for(i = 0; i < NUM_COLUMNS; i++)
2336 data->column_maxwidth[i] = 0;
2339 SetAttrs(obj, MUIA_TextIconList_Left, data->view_x,
2340 MUIA_TextIconList_Top, data->view_y,
2341 MUIA_TextIconList_Width, data->width,
2342 MUIA_TextIconList_Height, data->height,
2343 TAG_DONE);
2345 data->update = UPDATE_ALL;
2346 MUI_Redraw(obj,MADF_DRAWUPDATE);
2347 return 1;
2350 /**************************************************************************
2351 MUIM_TextIconList_Add.
2352 Returns 0 on failure otherwise 1
2353 **************************************************************************/
2354 static IPTR TextIconList_Add(struct IClass *cl, Object *obj, struct MUIP_TextIconList_Add *msg)
2356 struct TextIconList_DATA *data = INST_DATA(cl, obj);
2357 struct TextIconEntry *entry;
2358 struct DateTime dt;
2359 UBYTE *sp;
2361 if (!(entry = AllocPooled(data->pool,sizeof(struct TextIconEntry))))
2363 return 0;
2366 memset(entry, 0, sizeof(struct TextIconEntry));
2368 entry->fib = *msg->fib;
2370 if (entry->fib.fib_DirEntryType > 0)
2372 strcpy(GetTextIconEntryText(data, entry, INDEX_SIZE), "Drawer");
2374 else
2376 sprintf(GetTextIconEntryText(data, entry, INDEX_SIZE), "%ld", (long)entry->fib.fib_Size);
2379 dt.dat_Stamp = entry->fib.fib_Date;
2380 dt.dat_Format = FORMAT_DOS;
2381 dt.dat_Flags = 0;
2382 dt.dat_StrDay = NULL;
2383 dt.dat_StrDate = GetTextIconEntryText(data, entry, INDEX_DATE);
2384 dt.dat_StrTime = GetTextIconEntryText(data, entry, INDEX_TIME);;
2386 DateToStr(&dt);
2388 sp = GetTextIconEntryText(data, entry, INDEX_PROTECTION);
2389 *sp++ = (entry->fib.fib_Protection & FIBF_SCRIPT) ? 's' : '-';
2390 *sp++ = (entry->fib.fib_Protection & FIBF_PURE) ? 'p' : '-';
2391 *sp++ = (entry->fib.fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
2392 *sp++ = (entry->fib.fib_Protection & FIBF_READ) ? '-' : 'r';
2393 *sp++ = (entry->fib.fib_Protection & FIBF_WRITE) ? '-' : 'w';
2394 *sp++ = (entry->fib.fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
2395 *sp++ = (entry->fib.fib_Protection & FIBF_DELETE) ? '-' : 'd';
2396 *sp++ = '\0';
2398 data->num_entries++;
2400 SortInNode(data, (struct List *)&data->entries_list, (struct Node *)entry, (APTR)CompareNodes);
2402 if (data->is_setup)
2404 CalcEntryDimension(data, entry);
2405 data->height += data->lineheight;
2407 CalcWidth(data);
2409 SetAttrs(obj, MUIA_TextIconList_Width, data->width,
2410 MUIA_TextIconList_Height, data->height,
2411 TAG_DONE);
2414 return 1;
2417 BOOPSI_DISPATCHER(IPTR,TextIconList_Dispatcher, cl, obj, msg)
2419 switch (msg->MethodID)
2422 case OM_NEW: return TextIconList_New(cl, obj, (struct opSet *)msg);
2423 case OM_DISPOSE: return TextIconList_Dispose(cl,obj, msg);
2424 case OM_SET: return TextIconList_Set(cl,obj,(struct opSet *)msg);
2425 case OM_GET: return TextIconList_Get(cl,obj,(struct opGet *)msg);
2426 case MUIM_Setup: return TextIconList_Setup(cl,obj,(struct MUIP_Setup *)msg);
2427 case MUIM_Show: return TextIconList_Show(cl,obj,(struct MUIP_Show *)msg);
2428 case MUIM_Hide: return TextIconList_Hide(cl,obj,(struct MUIP_Hide *)msg);
2429 case MUIM_Cleanup: return TextIconList_Cleanup(cl,obj,(struct MUIP_Cleanup *)msg);
2430 case MUIM_AskMinMax: return TextIconList_AskMinMax(cl,obj,(struct MUIP_AskMinMax *)msg);
2431 case MUIM_Draw: return TextIconList_Draw(cl,obj,(struct MUIP_Draw *)msg);
2432 // case MUIM_Layout: return TextIconList_Layout(cl,obj,(struct MUIP_Layout *)msg);
2433 case MUIM_HandleEvent: return TextIconList_HandleEvent(cl,obj,(struct MUIP_HandleEvent *)msg);
2434 // case MUIM_CreateDragImage: return TextIconList_CreateDragImage(cl,obj,(APTR)msg);
2435 // case MUIM_DeleteDragImage: return TextIconList_DeleteDragImage(cl,obj,(APTR)msg);
2436 // case MUIM_DragQuery: return TextIconList_DragQuery(cl,obj,(APTR)msg);
2437 // case MUIM_DragReport: return TextIconList_DragReport(cl,obj,(APTR)msg);
2438 // case MUIM_DragDrop: return TextIconList_DragDrop(cl,obj,(APTR)msg);
2440 // case MUIM_TextIconList_Update: return TextIconList_Update(cl,obj,(APTR)msg);
2441 case MUIM_TextIconList_Clear: return TextIconList_Clear(cl,obj,(APTR)msg);
2442 case MUIM_TextIconList_Add: return TextIconList_Add(cl,obj,(APTR)msg);
2443 // case MUIM_TextIconList_NextSelected: return TextIconList_NextSelected(cl,obj,(APTR)msg);
2444 // case MUIM_TextIconList_UnselectAll: return TextIconList_UnselectAll(cl,obj,(APTR)msg);
2446 case MUIM_TextIconList_AutoScroll: return TextIconList_AutoScroll(cl,obj,(APTR)msg);
2449 return DoSuperMethodA(cl, obj, msg);
2451 BOOPSI_DISPATCHER_END
2453 /*================ TextIconListview class ===================*/
2455 #define MUIB_TextIconListview (MUIB_AROS | 0x00000800)
2457 #define MUIA_TextIconListview_TextIconList (MUIB_TextIconListview | 0x00000000)
2458 #define MUIA_TextIconListview_UseWinBorder (MUIB_TextIconListview | 0x00000001)
2460 #define TextIconListviewObject BOOPSIOBJMACRO_START(CL_TextIconListview->mcc_Class)
2462 struct TextIconListview_DATA
2464 Object *texticonlist;
2465 Object *vert, *horiz, *button;
2466 struct Hook hook;
2467 struct Hook layout_hook;
2471 IPTR TextIconListview_Layout_Function(struct Hook *hook, Object *obj, struct MUI_LayoutMsg *lm)
2473 struct TextIconListview_DATA *data = (struct TextIconListview_DATA *)hook->h_Data;
2475 switch (lm->lm_Type)
2477 case MUILM_MINMAX:
2479 /* Calulate the minmax dimension of the group,
2480 ** We only have a fixed number of children, so we need no NextObject()
2482 WORD maxxxxwidth = 0;
2483 WORD maxxxxheight = 0;
2485 maxxxxwidth = _minwidth(data->texticonlist) + _minwidth(data->vert);
2486 if (_minwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _minwidth(data->horiz);
2487 lm->lm_MinMax.MinWidth = maxxxxwidth;
2489 maxxxxheight = _minheight(data->texticonlist) + _minheight(data->horiz);
2490 if (_minheight(data->vert) > maxxxxheight) maxxxxheight = _minheight(data->vert);
2491 lm->lm_MinMax.MinHeight = maxxxxheight;
2493 maxxxxwidth = _defwidth(data->texticonlist) + _defwidth(data->vert);
2494 if (_defwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _defwidth(data->horiz);
2495 lm->lm_MinMax.DefWidth = maxxxxwidth;
2497 maxxxxheight = _defheight(data->texticonlist) + _defheight(data->horiz);
2498 if (_defheight(data->vert) > maxxxxheight) maxxxxheight = _defheight(data->vert);
2499 lm->lm_MinMax.DefHeight = maxxxxheight;
2501 lm->lm_MinMax.MaxWidth = MUI_MAXMAX;
2502 lm->lm_MinMax.MaxHeight = MUI_MAXMAX;
2504 return 0;
2507 case MUILM_LAYOUT:
2509 /* Now place the objects between (0,0,lm->lm_Layout.Width-1,lm->lm_Layout.Height-1)
2512 LONG virt_width = 0;
2513 LONG virt_height = 0;
2514 LONG vert_width = _minwidth(data->vert);
2515 LONG horiz_height = _minheight(data->horiz);
2516 LONG lay_width = lm->lm_Layout.Width;
2517 LONG lay_height = lm->lm_Layout.Height;
2518 LONG cont_width;
2519 LONG cont_height;
2521 /* layout the virtual group a first time, to determine the virtual width/height */
2522 MUI_Layout(data->texticonlist,0,0,lay_width,lay_height,0);
2524 get(data->texticonlist, MUIA_TextIconList_Width, &virt_width);
2525 get(data->texticonlist, MUIA_TextIconList_Height, &virt_height);
2527 virt_width += _subwidth(data->texticonlist);
2528 virt_height += _subheight(data->texticonlist);
2530 if (virt_width > lay_width && virt_height > lay_height)
2532 /* We need all scrollbars and the button */
2533 set(data->vert, MUIA_ShowMe, TRUE); /* We could also overload MUIM_Show... */
2534 set(data->horiz, MUIA_ShowMe, TRUE);
2535 set(data->button, MUIA_ShowMe, TRUE);
2536 cont_width = lay_width - vert_width;
2537 cont_height = lay_height - horiz_height;
2538 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
2539 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
2540 MUI_Layout(data->button, cont_width, cont_height, vert_width, horiz_height, 0);
2541 } else
2543 if (virt_height > lay_height)
2545 set(data->vert, MUIA_ShowMe, TRUE);
2546 set(data->horiz, MUIA_ShowMe, FALSE);
2547 set(data->button, MUIA_ShowMe, FALSE);
2549 cont_width = lay_width - vert_width;
2550 cont_height = lay_height;
2551 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
2552 } else
2554 if (virt_width > lay_width)
2556 set(data->vert, MUIA_ShowMe, FALSE);
2557 set(data->horiz, MUIA_ShowMe, TRUE);
2558 set(data->button, MUIA_ShowMe, FALSE);
2560 cont_width = lay_width;
2561 cont_height = lay_height - horiz_height;
2562 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
2563 } else
2565 set(data->vert, MUIA_ShowMe, FALSE);
2566 set(data->horiz, MUIA_ShowMe, FALSE);
2567 set(data->button, MUIA_ShowMe, FALSE);
2569 cont_width = lay_width;
2570 cont_height = lay_height;
2575 /* Layout the group a second time, note that setting _mwidth() and _mheight() should be enough, or we invent a new flag */
2576 MUI_Layout(data->texticonlist,0,0,cont_width,cont_height,0);
2577 return 1;
2580 return 0;
2584 IPTR TextIconListview_Function(struct Hook *hook, APTR dummyobj, void **msg)
2586 struct TextIconListview_DATA *data = (struct TextIconListview_DATA *)hook->h_Data;
2587 int type = (int)(IPTR)msg[0];
2588 LONG val = (LONG)(IPTR)msg[1];
2590 switch (type)
2592 case 1:
2594 get(data->vert,MUIA_Prop_First,&val);
2595 SetAttrs(data->texticonlist,MUIA_TextIconList_Top, val, MUIA_NoNotify, TRUE, TAG_DONE);
2596 break;
2599 case 2:
2601 get(data->horiz,MUIA_Prop_First,&val);
2602 SetAttrs(data->texticonlist,MUIA_TextIconList_Left, val, MUIA_NoNotify, TRUE, TAG_DONE);
2603 break;
2605 case 3: nnset(data->horiz, MUIA_Prop_First, val); break;
2606 case 4: nnset(data->vert, MUIA_Prop_First, val); break;
2608 return 0;
2612 IPTR TextIconListview__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2614 struct TextIconListview_DATA *data;
2615 //struct TagItem *tags,*tag;
2616 Object *texticonlist = (Object*)GetTagData(MUIA_TextIconListview_TextIconList, 0, msg->ops_AttrList);
2617 Object *vert,*horiz,*button,*group;
2619 int usewinborder;
2621 usewinborder = GetTagData(MUIA_TextIconListview_UseWinBorder, FALSE, msg->ops_AttrList);
2623 if (!usewinborder) button = ScrollbuttonObject, End;
2624 else button = NULL;
2626 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
2627 MUIA_Group_Horiz, FALSE,
2628 Child, (IPTR) (group = GroupObject,
2629 Child, (IPTR) texticonlist,
2630 Child, (IPTR) (vert = ScrollbarObject,
2631 usewinborder ? MUIA_Prop_UseWinBorder : TAG_IGNORE, MUIV_Prop_UseWinBorder_Right,
2632 MUIA_Prop_DeltaFactor, 20,
2633 MUIA_Group_Horiz, FALSE,
2634 End),
2635 Child, (IPTR) (horiz = ScrollbarObject,
2636 usewinborder?MUIA_Prop_UseWinBorder:TAG_IGNORE, MUIV_Prop_UseWinBorder_Bottom,
2637 MUIA_Prop_DeltaFactor, 20,
2638 MUIA_Group_Horiz, TRUE,
2639 End),
2640 usewinborder ? TAG_IGNORE : Child, (IPTR) button,
2641 End),
2642 TAG_DONE);
2644 if (!obj)
2646 return 0;
2649 data = INST_DATA(cl, obj);
2650 data->vert = vert;
2651 data->horiz = horiz;
2652 data->button = button;
2653 data->texticonlist = texticonlist;
2655 if (!usewinborder)
2657 data->layout_hook.h_Entry = HookEntry;
2658 data->layout_hook.h_SubEntry = (HOOKFUNC)TextIconListview_Layout_Function;
2659 data->layout_hook.h_Data = data;
2661 SetAttrs(group, MUIA_Group_Forward, FALSE,
2662 MUIA_Group_LayoutHook, (IPTR) &data->layout_hook,
2663 TAG_DONE);
2666 data->hook.h_Entry = HookEntry;
2667 data->hook.h_SubEntry = (HOOKFUNC)TextIconListview_Function;
2668 data->hook.h_Data = data;
2670 DoMethod(vert, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 1, MUIV_TriggerValue);
2671 DoMethod(horiz, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 2, MUIV_TriggerValue);
2672 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Left, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 3, MUIV_TriggerValue);
2673 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Top, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 4, MUIV_TriggerValue);
2674 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Width, MUIV_EveryTime, (IPTR)horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
2675 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Height, MUIV_EveryTime, (IPTR)vert, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
2676 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_VisWidth, MUIV_EveryTime, (IPTR)horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
2677 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_VisHeight, MUIV_EveryTime, (IPTR)vert, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
2679 return (IPTR)obj;
2683 IPTR TextIconListview__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2685 //struct TextIconListview_DATA *data = INST_DATA(cl, obj);
2687 return DoSuperMethodA(cl,obj,msg);
2690 IPTR TextIconListview__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
2692 struct TextIconListview_DATA *data = INST_DATA(cl, obj);
2693 IPTR top = 0,left = 0,width = 0,height = 0,viswidth = 0,visheight = 0;
2695 get(data->texticonlist, MUIA_TextIconList_Left, &left);
2696 get(data->texticonlist, MUIA_TextIconList_Top, &top);
2697 get(data->texticonlist, MUIA_TextIconList_Width, &width);
2698 get(data->texticonlist, MUIA_TextIconList_Height, &height);
2699 get(data->texticonlist, MUIA_TextIconList_VisWidth, &viswidth);
2700 get(data->texticonlist, MUIA_TextIconList_VisHeight, &visheight);
2702 SetAttrs(data->horiz, MUIA_Prop_First, left,
2703 MUIA_Prop_Entries, width,
2704 MUIA_Prop_Visible, viswidth,
2705 TAG_DONE);
2708 SetAttrs(data->vert, MUIA_Prop_First, top,
2709 MUIA_Prop_Entries, height,
2710 MUIA_Prop_Visible, visheight,
2711 TAG_DONE);
2713 return DoSuperMethodA(cl,obj,(Msg)msg);
2716 BOOPSI_DISPATCHER(IPTR,TextIconListview_Dispatcher, cl, obj, msg)
2718 switch (msg->MethodID)
2720 case OM_NEW: return TextIconListview__OM_NEW(cl, obj, (struct opSet *) msg);
2721 case OM_DISPOSE: return TextIconListview__OM_DISPOSE(cl, obj, msg);
2722 case MUIM_Show: return TextIconListview__MUIM_Show(cl, obj, (struct MUIP_Show*)msg);
2725 return DoSuperMethodA(cl, obj, msg);
2728 BOOPSI_DISPATCHER_END
2731 int main(void)
2733 Object *wnd, *texticonlist;
2734 #if 0
2735 Object *iconlist;
2736 #endif
2738 MUIMasterBase = (struct Library*)OpenLibrary("muimaster.library",0);
2740 CL_TextIconListview = MUI_CreateCustomClass(NULL,MUIC_Group,NULL,sizeof(struct TextIconListview_DATA), TextIconListview_Dispatcher);
2741 CL_TextIconList = MUI_CreateCustomClass(NULL,MUIC_Area,NULL,sizeof(struct TextIconList_DATA), TextIconList_Dispatcher);
2743 app = ApplicationObject,
2744 SubWindow, (IPTR) (wnd = WindowObject,
2745 MUIA_Window_Title, (IPTR) "texticonlist",
2746 MUIA_Window_Activate, TRUE,
2748 WindowContents, (IPTR) VGroup,
2749 MUIA_Background, MUII_GroupBack,
2750 #if 0
2751 Child, (IPTR) IconListviewObject,
2752 MUIA_IconListview_IconList, (IPTR) (iconlist = IconDrawerListObject,
2753 InputListFrame,
2754 MUIA_IconDrawerList_Drawer, (IPTR) "C:",
2755 End),
2756 End,
2757 #endif
2758 Child, (IPTR) TextIconListviewObject,
2759 // MUIA_TextIconListview_UseWinBorder, TRUE,
2760 MUIA_TextIconListview_TextIconList, (IPTR) (texticonlist = TextIconListObject,
2761 InputListFrame,
2762 InnerSpacing(0,0),
2763 End),
2764 End,
2767 Child, (IPTR) (texticonlist = TextIconListObject, InputListFrame, End),
2769 End,
2770 End),
2771 End;
2773 if (app)
2775 ULONG sigs = 0;
2777 DoMethod
2779 wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, (IPTR) app,
2780 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit
2784 BPTR lock = Lock("C:", SHARED_LOCK);
2786 if (lock)
2788 struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, NULL);
2789 if (fib)
2791 if (Examine(lock, fib))
2793 while(ExNext(lock, fib))
2795 DoMethod(texticonlist, MUIM_TextIconList_Add, (IPTR) fib);
2799 FreeDosObject(DOS_FIB, fib);
2802 UnLock(lock);
2806 set(wnd,MUIA_Window_Open,TRUE);
2807 #if 0
2808 set(iconlist, MUIA_IconDrawerList_Drawer, "C:");
2809 #endif
2811 while (DoMethod(app, MUIM_Application_NewInput, (IPTR) &sigs) != MUIV_Application_ReturnID_Quit)
2813 if (sigs)
2815 sigs = Wait(sigs | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
2816 if (sigs & SIGBREAKF_CTRL_C) break;
2817 if (sigs & SIGBREAKF_CTRL_D) break;
2821 MUI_DisposeObject(app);
2824 MUI_DeleteCustomClass(CL_TextIconList);
2825 MUI_DeleteCustomClass(CL_TextIconListview);
2827 CloseLibrary(MUIMasterBase);
2829 return 0;