r4493@vps: verhaegs | 2007-04-19 14:44:00 -0400
[AROS.git] / test / Zune / texticonlist.c
blob793dd233ae818e087c526f3a58efef39a7e7122e
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 struct Library *MUIMasterBase;
36 Object *app;
37 struct MUI_CustomClass *CL_TextIconList, *CL_TextIconListview;
39 /*================== TextIconList class =====================*/
41 #define NUM_COLUMNS 6
43 #define MIN_COLUMN_WIDTH 10
45 #define COLUMN_ALIGN_LEFT 0
46 #define COLUMN_ALIGN_CENTER 1
47 #define COLUMN_ALIGN_RIGHT 2
49 #define LINE_SPACING_TOP 2
50 #define LINE_SPACING_BOTTOM 2
51 #define LINE_EXTRAHEIGHT (LINE_SPACING_TOP + LINE_SPACING_BOTTOM)
53 #define LINE_SPACING_LEFT 1
54 #define LINE_SPACING_RIGHT 1
55 #define LINE_EXTRAWIDTH (LINE_SPACING_LEFT + LINE_SPACING_RIGHT)
57 #define ENTRY_SPACING_LEFT 1
58 #define ENTRY_SPACING_RIGHT 1
59 #define ENTRY_EXTRAWIDTH (ENTRY_SPACING_LEFT + ENTRY_SPACING_RIGHT)
61 #define HEADERLINE_SPACING_TOP 3
62 #define HEADERLINE_SPACING_BOTTOM 3
63 #define HEADERLINE_EXTRAHEIGHT (HEADERLINE_SPACING_TOP + HEADERLINE_SPACING_BOTTOM)
65 #define HEADERLINE_SPACING_LEFT 1
66 #define HEADERLINE_SPACING_RIGHT 1
67 #define HEADERLINE_EXTRAWIDTH (HEADERLINE_SPACING_LEFT + HEADERLINE_SPACING_RIGHT)
69 #define HEADERENTRY_SPACING_LEFT 4
70 #define HEADERENTRY_SPACING_RIGHT 4
71 #define HEADERENTRY_EXTRAWIDTH (HEADERENTRY_SPACING_LEFT + HEADERENTRY_SPACING_RIGHT)
73 #define AUTOSCROLL_MILLIS 20
75 struct TextIconEntry
77 struct MinNode node;
78 struct MinNode selection_node;
79 struct FileInfoBlock fib;
80 LONG field_width[NUM_COLUMNS];
81 UBYTE datebuf[LEN_DATSTRING];
82 UBYTE timebuf[LEN_DATSTRING];
83 UBYTE sizebuf[30];
84 UBYTE protbuf[8];
85 UBYTE selected;
86 UBYTE dirty;
89 struct MyColor
91 ULONG pixel;
92 ULONG rgbpixel;
93 UBYTE alloced;
96 #define COLOR_COLUMN_BACKGROUND 0
97 #define COLOR_COLUMN_BACKGROUND_SORTED 1
98 #define COLOR_COLUMN_BACKGROUND_LASSO 2
99 #define COLOR_COLUMN_BACKGROUND_LASSO_SORTED 3
101 #define COLOR_SELECTED_BACKGROUND 4
102 #define COLOR_SELECTED_BACKGROUND_SORTED 5
103 #define COLOR_SELECTED_BACKGROUND_LASSO 6
104 #define COLOR_SELECTED_BACKGROUND_LASSO_SORTED 7
106 #define NUM_COLORS 8
108 static const ULONG rgb_colors[NUM_COLORS] =
110 0xFFFFFF,
111 0xF0F0F0,
112 0xE4E7Ef,
113 0xDEE1E9,
114 0x0A246A,
115 0x0A246A,
116 0x324882,
117 0x324882
120 static const ULONG pen_colors[NUM_COLORS] =
122 MPEN_SHINE,
123 MPEN_SHINE,
124 MPEN_BACKGROUND,
125 MPEN_BACKGROUND,
126 MPEN_FILL,
127 MPEN_FILL,
128 MPEN_FILL,
129 MPEN_FILL
132 struct TextIconList_DATA
134 APTR pool;
135 LONG view_x, view_y;
136 LONG view_width, view_height;
137 LONG width, height, lineheight, headerheight;
138 LONG update;
139 LONG update_scrolldx;
140 LONG update_scrolldy;
141 LONG update_entry;
142 struct MinList entries_list;
143 struct MinList selection_list;
144 struct RastPort temprp;
145 struct Rectangle view_rect;
146 struct Rectangle header_rect;
147 struct Rectangle lasso_rect, old_lasso_rect;
148 struct Rectangle *update_rect1, *update_rect2;
149 struct MyColor colors[NUM_COLORS];
150 LONG num_entries;
151 LONG num_selected;
152 LONG active_entry;
153 LONG click_x, click_y, click_column;
154 LONG column_pos[NUM_COLUMNS];
155 LONG column_maxwidth[NUM_COLUMNS];
156 LONG column_width[NUM_COLUMNS];
157 BYTE column_visible[NUM_COLUMNS];
158 BYTE column_align[NUM_COLUMNS];
159 BYTE column_clickable[NUM_COLUMNS];
160 BYTE column_sortable[NUM_COLUMNS];
161 STRPTR column_title[NUM_COLUMNS];
162 BYTE sort_column;
163 BYTE sort_direction;
164 BYTE sort_dirs;
165 LONG inputstate;
166 BOOL show_header;
167 BOOL is_setup;
168 BOOL is_shown;
169 BOOL lasso_active;
170 BOOL lasso_paint;
171 BOOL truecolor;
173 struct MUI_EventHandlerNode ehn;
174 struct MUI_InputHandlerNode thn;
177 #define UPDATE_SCROLL 2
178 #define UPDATE_DIRTY_ENTRIES 3
179 #define UPDATE_ALL 4
180 #define UPDATE_HEADER 5
182 #define INPUTSTATE_NONE 0
183 #define INPUTSTATE_PAN 1
184 #define INPUTSTATE_COL_RESIZE 2
185 #define INPUTSTATE_COL_HEADER_CLICK 3
186 #define INPUTSTATE_LASSO 4
188 #define MUIB_TextIconList (MUIB_AROS | 0x00000700)
190 #define MUIA_TextIconList_Left (MUIB_TextIconList | 0x00000000)
191 #define MUIA_TextIconList_Top (MUIB_TextIconList | 0x00000001)
192 #define MUIA_TextIconList_Width (MUIB_TextIconList | 0x00000002)
193 #define MUIA_TextIconList_Height (MUIB_TextIconList | 0x00000003)
194 #define MUIA_TextIconList_VisWidth (MUIB_TextIconList | 0x00000004)
195 #define MUIA_TextIconList_VisHeight (MUIB_TextIconList | 0x00000005)
197 #define MUIM_TextIconList_Clear (MUIB_TextIconList | 0x00000000)
198 #define MUIM_TextIconList_Add (MUIB_TextIconList | 0x00000001)
199 #define MUIM_TextIconList_AutoScroll (MUIB_TextIconList | 0x00000002)
201 struct MUIP_TextIconList_Clear {STACKULONG MethodID;};
202 struct MUIP_TextIconList_Add {STACKULONG MethodID; struct FileInfoBlock *fib;};
204 #define TextIconListObject BOOPSIOBJMACRO_START(CL_TextIconList->mcc_Class)
207 #define INDEX_NAME 0
208 #define INDEX_SIZE 1
209 #define INDEX_PROTECTION 2
210 #define INDEX_DATE 3
211 #define INDEX_TIME 4
212 #define INDEX_COMMENT 5
214 #define SORT_DRAWERS_FIRST 0
215 #define SORT_DRAWERS_MIXED 1
216 #define SORT_DRAWERS_LAST 2
218 #define SORT_DIRECTION_UP 0
219 #define SORT_DIRECTION_DOWN 1
221 #define SORT_BY_NAME 0
222 #define SORT_BY_DATE 1
223 #define SORT_BY_SIZE 2
225 static STRPTR GetTextIconEntryText(struct TextIconList_DATA *data, struct TextIconEntry *entry,
226 LONG index)
228 STRPTR ret = 0;
230 switch(index)
232 case INDEX_NAME:
233 ret = entry->fib.fib_FileName;
234 break;
236 case INDEX_SIZE:
237 ret = entry->sizebuf;
238 break;
240 case INDEX_DATE:
241 ret = entry->datebuf;
242 break;
244 case INDEX_TIME:
245 ret = entry->timebuf;
246 break;
248 case INDEX_COMMENT:
249 ret = entry->fib.fib_Comment;
250 break;
252 case INDEX_PROTECTION:
253 ret = entry->protbuf;
254 break;
257 return ret;
260 static STRPTR GetTextIconHeaderText(struct TextIconList_DATA *data, LONG index)
262 STRPTR ret = 0;
264 ret = data->column_title[index];
265 if (ret) return ret;
267 switch(index)
269 case INDEX_NAME:
270 ret = "Name";
271 break;
273 case INDEX_SIZE:
274 ret = "Size";
275 break;
277 case INDEX_DATE:
278 ret = "Date";
279 break;
281 case INDEX_TIME:
282 ret = "Time";
283 break;
285 case INDEX_COMMENT:
286 ret = "Comment";
287 break;
289 case INDEX_PROTECTION:
290 ret = "Protection";
291 break;
294 return ret;
297 static void CalcWidth(struct TextIconList_DATA *data)
299 LONG i, width = LINE_EXTRAWIDTH;
301 for(i = 0; i < NUM_COLUMNS; i++)
303 if (data->column_visible[i])
305 width += data->column_width[i];
309 data->width = width;
312 static void CalcEntryDimension(struct TextIconList_DATA *data, struct TextIconEntry *entry)
314 LONG i;
315 STRPTR text;
316 LONG len;
318 for (i = 0; i < NUM_COLUMNS; i++)
320 text = GetTextIconEntryText(data, entry, i);
321 len = TextLength(&data->temprp, text, strlen(text));
323 entry->field_width[i] = len + ENTRY_EXTRAWIDTH;
325 if (entry->field_width[i] > data->column_maxwidth[i])
327 data->column_maxwidth[i] = entry->field_width[i];
333 static void CalcAllEntryDimensions(struct TextIconList_DATA *data)
335 struct TextIconEntry *entry;
337 ForeachNode(&data->entries_list, entry)
339 CalcEntryDimension(data, entry);
343 static void RecalcColumnMaxWidths(struct TextIconList_DATA *data)
345 struct TextIconEntry *entry;
346 LONG i;
348 for(i = 0; i < NUM_COLUMNS; i++)
350 data->column_maxwidth[i] = 0;
353 ForeachNode(&data->entries_list, entry)
355 for(i = 0; i < NUM_COLUMNS; i++)
357 if (entry->field_width[i] > data->column_maxwidth[i])
359 data->column_maxwidth[i] = entry->field_width[i];
365 static LONG FirstVisibleColumnNumber(struct TextIconList_DATA *data)
367 LONG i;
368 LONG retval = -1;
370 for(i = 0; i < NUM_COLUMNS; i++)
372 LONG index = data->column_pos[i];
374 if (data->column_visible[index])
376 retval = i;
377 break;
381 return retval;
384 static LONG LastVisibleColumnNumber(struct TextIconList_DATA *data)
386 LONG i;
387 LONG retval = -1;
389 for(i = 0; i < NUM_COLUMNS; i++)
391 LONG index = data->column_pos[i];
393 if (data->column_visible[index])
395 retval = i;
399 return retval;
403 static struct TextIconEntry *GetEntryFromIndex(struct TextIconList_DATA *data, LONG index)
405 struct TextIconEntry *node;
406 struct TextIconEntry *retval = 0;
407 ULONG i = 0;
409 if (index >= 0 && index < data->num_entries)
411 ForeachNode(&data->entries_list, node)
413 if (i == index)
415 retval = node;
416 break;
418 i++;
422 return retval;
425 static LONG LineUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
427 LONG index = -1;
429 if ((mx >= data->view_rect.MinX) &&
430 (my >= data->view_rect.MinY) &&
431 (mx <= data->view_rect.MaxX) &&
432 (my <= data->view_rect.MaxY))
434 index = (my - data->view_rect.MinY + data->view_y) / data->lineheight;
436 if ((index < 0) || (index >= data->num_entries)) index = -1;
439 return index;
442 static LONG ColumnUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
444 LONG col = -1;
446 if ((mx >= data->view_rect.MinX) &&
447 (my >= data->view_rect.MinY - data->headerheight) &&
448 (mx <= data->view_rect.MaxX) &&
449 (my <= data->view_rect.MaxY))
451 LONG x = data->view_rect.MinX - data->view_x + LINE_SPACING_LEFT;
452 LONG w, i;
454 for(i = 0; i < NUM_COLUMNS; i++)
456 LONG index = data->column_pos[i];
458 if (!data->column_visible[index]) continue;
460 w = data->column_width[index];
462 if ((mx >= x) && (mx < x + w))
464 col = index;
465 break;
467 x += w;
472 return col;
475 static LONG ColumnHeaderUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
477 LONG col = -1;
479 if (data->show_header &&
480 (my >= data->header_rect.MinY) &&
481 (my <= data->header_rect.MaxY))
483 col = ColumnUnderMouse(data, mx, my);
486 return col;
489 static LONG ColumnResizeHandleUnderMouse(struct TextIconList_DATA *data, LONG mx, LONG my)
491 LONG col = -1;
493 if ((mx >= data->view_rect.MinX) &&
494 (my >= data->view_rect.MinY - data->headerheight) &&
495 (mx <= data->view_rect.MaxX) &&
496 (my <= data->view_rect.MaxY))
498 LONG x = data->view_rect.MinX - data->view_x + LINE_SPACING_LEFT;
499 LONG w, i;
501 for(i = 0; i < NUM_COLUMNS; i++)
503 LONG index = data->column_pos[i];
505 if (!data->column_visible[index]) continue;
507 w = data->column_width[index];
509 if (abs(mx - (x + w - 1)) <= 4)
511 col = index;
512 break;
514 x += w;
519 return col;
522 static BOOL GetColumnCoords(struct TextIconList_DATA *data, LONG index, LONG *x1, LONG *x2)
524 LONG i;
525 BOOL retval = FALSE;
526 LONG x = data->view_rect.MinX - data->view_x + LINE_SPACING_LEFT;
527 LONG firstvis, lastvis;
529 firstvis = FirstVisibleColumnNumber(data);
530 lastvis = LastVisibleColumnNumber(data);
532 for(i = 0; i < NUM_COLUMNS; i++)
534 LONG idx = data->column_pos[i];
535 LONG w;
537 if (!data->column_visible[idx]) continue;
539 w = data->column_width[idx];
541 if (idx == index)
543 retval = TRUE;
544 *x1 = x - ((i == firstvis) ? LINE_SPACING_LEFT : 0);
545 *x2 = x + w - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
546 break;
549 x += w;
552 return retval;
555 static LONG CompareNodes(struct TextIconList_DATA *data, struct TextIconEntry *node1, struct TextIconEntry *node2)
557 LONG pri1 = (node1->fib.fib_DirEntryType > 0) ? 1 : 0;
558 LONG pri2 = (node2->fib.fib_DirEntryType > 0) ? 1 : 0;
559 LONG diff = (pri2 - pri1) * -(data->sort_dirs - 1);
561 if (!diff)
563 switch(data->sort_column)
565 case INDEX_DATE:
566 case INDEX_TIME:
567 diff = CompareDates((const struct DateStamp *)&node2->fib.fib_Date,
568 (const struct DateStamp *)&node1->fib.fib_Date);
570 break;
572 case INDEX_SIZE:
573 if (node1->fib.fib_Size < node2->fib.fib_Size)
575 diff = -1;
577 else if (node1->fib.fib_Size > node2->fib.fib_Size)
579 diff = 1;
581 break;
583 default:
584 case INDEX_NAME:
585 diff = Stricmp(node1->fib.fib_FileName, node2->fib.fib_FileName);
586 break;
590 if (data->sort_direction == SORT_DIRECTION_DOWN) diff = -diff;
593 return diff;
596 static void SortInNode(struct TextIconList_DATA *data, struct List *list, struct Node *node,
597 LONG (*compare)(APTR data, APTR node1, APTR node2))
599 struct Node *prevnode = NULL;
600 struct Node *checknode;
602 ForeachNode(list, checknode)
604 if (compare(data, node, checknode) < 0) break;
606 prevnode = checknode;
609 Insert(list, node, prevnode);
612 static void ReSortEntries(struct TextIconList_DATA *data)
614 struct List templist;
615 struct Node *node, *succ;
617 NEWLIST(&templist);
619 ForeachNodeSafe(&data->entries_list, node, succ)
621 Remove(node);
622 AddTail(&templist, node);
625 ForeachNodeSafe(&templist, node, succ)
627 SortInNode(data, (struct List *)&data->entries_list, node, (APTR)CompareNodes);
631 static BOOL MustRenderRect(struct TextIconList_DATA *data, struct Rectangle *rect)
633 if (data->update_rect1 && data->update_rect2)
635 if (!AndRectRect(rect, data->update_rect1, NULL) &&
636 !AndRectRect(rect, data->update_rect2, NULL)) return FALSE;
638 else if (data->update_rect1)
640 if (!AndRectRect(rect, data->update_rect1, NULL)) return FALSE;
642 else if (data->update_rect2)
644 if (!AndRectRect(rect, data->update_rect2, NULL)) return FALSE;
647 return TRUE;
650 static void GetAbsoluteLassoRect(struct TextIconList_DATA *data, struct Rectangle *lasso_rect)
652 WORD minx = data->lasso_rect.MinX;
653 WORD miny = data->lasso_rect.MinY;
654 WORD maxx = data->lasso_rect.MaxX;
655 WORD maxy = data->lasso_rect.MaxY;
657 if (minx > maxx)
659 /* Swap minx, maxx */
660 minx ^= maxx;
661 maxx ^= minx;
662 minx ^= maxx;
665 if (miny > maxy)
667 /* Swap miny, maxy */
668 miny ^= maxy;
669 maxy ^= miny;
670 miny ^= maxy;
673 lasso_rect->MinX = data->view_rect.MinX - data->view_x + minx;
674 lasso_rect->MinY = data->view_rect.MinY - data->view_y + miny;
675 lasso_rect->MaxX = data->view_rect.MinX - data->view_x + maxx;
676 lasso_rect->MaxY = data->view_rect.MinY - data->view_y + maxy;
679 static void EnableMouseMoveEvents(Object *obj, struct TextIconList_DATA *data)
681 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
683 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
684 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
685 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
689 static void DisableMouseMoveEvents(Object *obj, struct TextIconList_DATA *data)
691 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
693 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
694 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
695 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
699 static void EnableAutoScrollTimer(Object *obj, struct TextIconList_DATA *data)
701 if (!data->thn.ihn_Millis)
703 data->thn.ihn_Millis = AUTOSCROLL_MILLIS;
704 DoMethod(_app(obj), MUIM_Application_AddInputHandler, (IPTR)&data->thn);
708 static void DisableAutoScrollTimer(Object *obj, struct TextIconList_DATA *data)
710 if (data->thn.ihn_Millis)
712 data->thn.ihn_Millis = 0;
713 DoMethod(_app(obj), MUIM_Application_RemInputHandler, (IPTR)&data->thn);
717 static BOOL OrRectOutlineRegion(struct Region *reg, struct Rectangle *rect)
719 struct Rectangle r;
720 BOOL result;
722 r.MinX = rect->MinX;
723 r.MinY = rect->MinY;
724 r.MaxX = rect->MaxX;
725 r.MaxY = rect->MinY;
726 result = OrRectRegion(reg, &r);
728 r.MinX = rect->MaxX;
729 r.MinY = rect->MinY;
730 r.MaxX = rect->MaxX;
731 r.MaxY = rect->MaxY;
732 result = result && OrRectRegion(reg, &r);
734 r.MinX = rect->MinX;
735 r.MinY = rect->MaxY;
736 r.MaxX = rect->MaxX;
737 r.MaxY = rect->MaxY;
738 result = result && OrRectRegion(reg, &r);
740 r.MinX = rect->MinX;
741 r.MinY = rect->MinY;
742 r.MaxX = rect->MinX;
743 r.MaxY = rect->MaxY;
744 result = result && OrRectRegion(reg, &r);
746 return result;
749 static void MyRectFill(struct TextIconList_DATA *data, struct RastPort *rp,
750 LONG x1, LONG y1, LONG x2, LONG y2, LONG mycol)
752 if (x1 > x2)
754 x1 ^= x2;
755 x2 ^= x1;
756 x1 ^= x2;
759 if (y1 > y2)
761 y1 ^= y2;
762 y2 ^= y1;
763 y1 ^= y2;
766 SetDrMd(rp, JAM1);
768 if (data->truecolor && CyberGfxBase)
770 FillPixelArray(rp, x1, y1, x2 - x1 + 1, y2 - y1 + 1, data->colors[mycol].rgbpixel);
772 else
774 SetAPen(rp, data->colors[mycol].pixel);
775 RectFill(rp, x1, y1, x2, y2);
779 static void RenderHeaderField(Object *obj, struct TextIconList_DATA *data,
780 struct Rectangle *rect, LONG index)
782 STRPTR text;
783 struct TextExtent te;
784 ULONG fit;
785 BOOL sel = FALSE;
787 if ((data->inputstate == INPUTSTATE_COL_HEADER_CLICK) &&
788 (data->click_column == index))
791 if (ColumnHeaderUnderMouse(data, data->click_x, data->click_y) == index)
793 sel = TRUE;
797 text = GetTextIconHeaderText(data, index);
799 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_HALFSHADOW : MPEN_HALFSHINE]);
800 RectFill(_rp(obj), rect->MinX + 1, rect->MinY + 1,
801 rect->MaxX - 1, rect->MaxY - 1);
802 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_SHADOW : MPEN_SHINE]);
803 RectFill(_rp(obj), rect->MinX, rect->MinY, rect->MinX, rect->MaxY);
804 RectFill(_rp(obj), rect->MinX + 1, rect->MinY, rect->MaxX - 1, rect->MinY);
805 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_HALFSHINE : MPEN_HALFSHADOW]);
806 RectFill(_rp(obj), rect->MaxX, rect->MinY, rect->MaxX, rect->MaxY);
807 RectFill(_rp(obj), rect->MinX + 1, rect->MaxY, rect->MaxX - 1, rect->MaxY);
809 if (index == data->sort_column)
811 LONG x = rect->MaxX - 4 - 6;
812 LONG y = (rect->MinY + rect->MaxY + 1) / 2 - 3;
814 if (x > rect->MinX)
816 SetAPen(_rp(obj), _pens(obj)[sel ? MPEN_SHADOW : MPEN_HALFSHADOW]);
817 if (data->sort_direction == SORT_DIRECTION_UP)
819 RectFill(_rp(obj), x, y, x + 5, y + 1);
820 RectFill(_rp(obj), x + 1, y + 2, x + 4, y + 3);
821 RectFill(_rp(obj), x + 2, y + 4, x + 3, y + 5);
823 else
825 RectFill(_rp(obj), x, y + 4, x + 5, y + 5);
826 RectFill(_rp(obj), x + 1, y + 2, x + 4, y + 3);
827 RectFill(_rp(obj), x + 2, y, x + 3, y + 1);
832 rect->MinX += HEADERENTRY_SPACING_LEFT;
833 rect->MinY += HEADERLINE_SPACING_TOP;
834 rect->MaxX -= HEADERENTRY_SPACING_RIGHT;
835 rect->MaxY -= HEADERLINE_SPACING_BOTTOM;
837 if (text && text[0])
839 fit = TextFit(_rp(obj), text, strlen(text), &te, NULL, 1,
840 rect->MaxX - rect->MinX + 1,
841 rect->MaxY - rect->MinY + 1);
843 if (!fit) return;
845 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_TEXT], 0, JAM1);
846 Move(_rp(obj), rect->MinX, rect->MinY + _rp(obj)->TxBaseline);
847 Text(_rp(obj), text, fit);
852 static void RenderHeaderline(Object *obj, struct TextIconList_DATA *data)
854 struct Rectangle linerect;
855 LONG x, i;
856 LONG firstvis, lastvis;
857 linerect = data->header_rect;
858 linerect.MinX -= data->view_x;
859 linerect.MaxX -= data->view_x;
861 linerect.MinX = data->header_rect.MinX - data->view_x;
862 linerect.MaxX = data->header_rect.MaxX; //linerect.MinX + data->width - 1;
863 linerect.MinY = data->header_rect.MinY;
864 linerect.MaxY = data->header_rect.MaxY;
866 if (!MustRenderRect(data, &linerect)) return;
868 SetFont(_rp(obj), _font(obj));
870 x = linerect.MinX + HEADERLINE_SPACING_LEFT;
872 firstvis = FirstVisibleColumnNumber(data);
873 lastvis = LastVisibleColumnNumber(data);
875 for(i = 0; i < NUM_COLUMNS; i++)
877 struct Rectangle field_rect;
878 LONG index = data->column_pos[i];
880 if (!data->column_visible[index]) continue;
882 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
883 field_rect.MinY = linerect.MinY;
884 field_rect.MaxX = x + data->column_width[index] - 1 + ((i == lastvis) ? HEADERLINE_SPACING_RIGHT : 0);
885 field_rect.MaxY = linerect.MaxY;
887 if (MustRenderRect(data, &field_rect))
889 RenderHeaderField(obj, data, &field_rect, index);
891 x += data->column_width[index];
894 x += HEADERLINE_SPACING_RIGHT;
896 if (x < linerect.MaxX)
898 linerect.MinX = x;
900 if (MustRenderRect(data, &linerect))
902 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_HALFSHINE], 0, JAM1);
903 RectFill(_rp(obj), linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
909 #define ENTRYPOS_FIRST -1
910 #define ENTRYPOS_MIDDLE 0
911 #define ENTRYPOS_LAST 1
913 static void RenderEntryField(Object *obj, struct TextIconList_DATA *data,
914 struct TextIconEntry *entry, struct Rectangle *rect,
915 LONG index, BOOL firstvis, BOOL lastvis)
917 STRPTR text;
918 struct TextExtent te;
919 ULONG fit;
920 BOOL selected;
922 selected = (entry && data->column_clickable[index]) ? entry->selected : FALSE;
924 fit = selected ? COLOR_SELECTED_BACKGROUND : COLOR_COLUMN_BACKGROUND;
925 if (index == data->sort_column) fit++;
926 if (data->lasso_paint) fit += 2;
928 MyRectFill(data, _rp(obj), rect->MinX, rect->MinY, rect->MaxX, rect->MaxY, fit);
930 rect->MinX += ENTRY_SPACING_LEFT;
931 rect->MaxX -= ENTRY_SPACING_RIGHT;
932 rect->MinY += LINE_SPACING_TOP;
933 rect->MaxY -= LINE_SPACING_BOTTOM;
935 if (firstvis) rect->MinX += LINE_SPACING_LEFT;
936 if (lastvis) rect->MaxX -= LINE_SPACING_RIGHT;
938 if (!entry) return;
940 text = GetTextIconEntryText(data, entry, index);
941 if (!text) return;
942 if (!text[0]) return;
944 fit = TextFit(_rp(obj), text, strlen(text), &te, NULL, 1,
945 rect->MaxX - rect->MinX + 1,
946 rect->MaxY - rect->MinY + 1);
948 if (!fit) return;
950 SetABPenDrMd(_rp(obj), _pens(obj)[selected ? MPEN_SHINE : MPEN_TEXT], 0, JAM1);
952 switch(data->column_align[index])
954 case COLUMN_ALIGN_LEFT:
955 Move(_rp(obj), rect->MinX, rect->MinY + _rp(obj)->TxBaseline);
956 break;
958 case COLUMN_ALIGN_RIGHT:
959 Move(_rp(obj), rect->MaxX - te.te_Width, rect->MinY + _rp(obj)->TxBaseline);
960 break;
962 case COLUMN_ALIGN_CENTER:
963 Move(_rp(obj), rect->MinX + (rect->MaxX - rect->MinX + 1 + 1 - te.te_Width) / 2,
964 rect->MinY + _rp(obj)->TxBaseline);
965 break;
968 Text(_rp(obj), text, fit);
971 static void RenderEntry(Object *obj, struct TextIconList_DATA *data, LONG index)
973 struct TextIconEntry *entry = GetEntryFromIndex(data, index);
974 struct Rectangle linerect;
975 LONG x, i;
976 LONG firstvis, lastvis;
978 linerect.MinX = data->view_rect.MinX - data->view_x;
979 linerect.MaxX = data->view_rect.MaxX; //linerect.MinX + data->width - 1;
980 linerect.MinY = data->view_rect.MinY + index * data->lineheight - data->view_y;
981 linerect.MaxY = linerect.MinY + data->lineheight - 1;
983 if (!AndRectRect(&linerect, &data->view_rect, NULL)) return;
984 if (!MustRenderRect(data, &linerect)) return;
986 SetFont(_rp(obj), _font(obj));
988 x = linerect.MinX + LINE_SPACING_LEFT;
990 firstvis = FirstVisibleColumnNumber(data);
991 lastvis = LastVisibleColumnNumber(data);
993 for(i = 0; i < NUM_COLUMNS; i++)
995 struct Rectangle field_rect;
996 LONG index = data->column_pos[i];
998 if (!data->column_visible[i]) continue;
1000 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
1001 field_rect.MinY = linerect.MinY;
1002 field_rect.MaxX = x + data->column_width[index] - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
1003 field_rect.MaxY = linerect.MaxY;
1005 if (MustRenderRect(data, &field_rect))
1007 if (AndRectRect(&field_rect, &data->view_rect, NULL))
1009 RenderEntryField(obj, data, entry, &field_rect, index,
1010 (i == firstvis), (i == lastvis));
1013 x += data->column_width[index];
1016 x += LINE_SPACING_RIGHT;
1018 if (x < linerect.MaxX)
1020 linerect.MinX = x;
1022 if (MustRenderRect(data, &linerect))
1024 SetABPenDrMd(_rp(obj), _pens(obj)[data->lasso_paint ? MPEN_BACKGROUND : MPEN_SHINE], 0, JAM1);
1025 RectFill(_rp(obj), linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
1031 static LONG FirstVisibleLine(struct TextIconList_DATA *data)
1033 return data->view_y / data->lineheight;
1036 static LONG NumVisibleLines(struct TextIconList_DATA *data)
1038 LONG visible = data->view_height + data->lineheight - 1 +
1039 (data->view_y % data->lineheight);
1041 visible /= data->lineheight;
1043 return visible;
1046 static void RenderAllEntries(Object *obj, struct TextIconList_DATA *data)
1048 LONG first = FirstVisibleLine(data);
1049 LONG visible = NumVisibleLines(data);
1050 LONG i;
1052 for(i = 0; i < visible; i++)
1054 RenderEntry(obj, data, first + i);
1060 static void RethinkLasso(Object *obj, struct TextIconList_DATA *data)
1062 struct TextIconEntry *entry;
1064 LONG ny1 = data->lasso_rect.MinY;
1065 LONG ny2 = data->lasso_rect.MaxY;
1066 LONG oy1 = data->old_lasso_rect.MinY;
1067 LONG oy2 = data->old_lasso_rect.MaxY;
1068 LONG y1, y2;
1069 LONG x1, x2;
1070 LONG numdirty = 0;
1071 BOOL lasso_hot;
1073 if (!data->num_entries) return;
1075 if (ny1 > ny2)
1077 ny1 ^= ny2;
1078 ny2 ^= ny1;
1079 ny1 ^= ny2;
1082 if (oy1 > oy2)
1084 oy1 ^= oy2;
1085 oy2 ^= oy1;
1086 oy1 ^= oy2;
1089 ny1 /= data->lineheight;
1090 ny2 /= data->lineheight;
1091 oy1 /= data->lineheight;
1092 oy2 /= data->lineheight;
1094 y1 = (ny1 < oy1) ? ny1 : oy1;
1095 y2 = (ny2 > oy2) ? ny2 : oy2;
1097 if (y1 < 0)
1099 y1 = 0;
1101 else if (y1 >= data->num_entries)
1103 y1 = data->num_entries - 1;
1106 if (y2 < 0)
1108 y2 = 0;
1110 else if (y2 >= data->num_entries)
1112 y2 = data->num_entries - 1;
1115 GetColumnCoords(data, INDEX_NAME, &x1, &x2);
1116 x1 += data->view_x - data->view_rect.MinX;
1117 x2 += data->view_x - data->view_rect.MinX;
1119 lasso_hot = ((data->lasso_rect.MinX >= x1) && (data->lasso_rect.MinX <= x2)) ||
1120 ((data->lasso_rect.MaxX >= x1) && (data->lasso_rect.MaxX <= x2)) ||
1121 ((data->lasso_rect.MinX < x1) && (data->lasso_rect.MaxX > x2)) ||
1122 ((data->lasso_rect.MaxX < x1) && (data->lasso_rect.MinX > x2));
1124 entry = GetEntryFromIndex(data, y1);
1125 while(entry && entry->node.mln_Succ && (y1 <= y2))
1127 BOOL select;
1129 select = (y1 >= ny1) && (y1 <= ny2) && lasso_hot;
1130 if (select != entry->selected)
1132 if (select)
1134 AddTail((struct List *)&data->selection_list, (struct Node *)&entry->selection_node);
1135 data->num_selected++;
1137 else
1139 Remove((struct Node *)&entry->selection_node);
1140 data->num_selected--;
1142 entry->selected = select;
1143 entry->dirty = TRUE;
1144 numdirty++;
1147 entry = (struct TextIconEntry *)entry->node.mln_Succ;
1148 y1++;
1151 if (numdirty)
1153 data->update = UPDATE_DIRTY_ENTRIES;
1154 MUI_Redraw(obj, MADF_DRAWUPDATE);
1159 /**************************************************************************
1160 OM_NEW
1161 **************************************************************************/
1162 static IPTR TextIconList_New(struct IClass *cl, Object *obj, struct opSet *msg)
1164 struct TextIconList_DATA *data;
1165 struct TagItem *tag, *tags;
1166 LONG i;
1168 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
1169 MUIA_FillArea, FALSE,
1170 TAG_MORE, (IPTR) msg->ops_AttrList);
1171 if (!obj) return FALSE;
1173 data = INST_DATA(cl, obj);
1174 NewList((struct List*)&data->entries_list);
1175 NewList((struct List*)&data->selection_list);
1176 data->show_header = TRUE;
1177 data->active_entry = -1;
1179 for(i = 0; i < NUM_COLUMNS; i++)
1181 data->column_pos[i] = i;
1182 data->column_visible[i] = TRUE;
1183 data->column_width[i] = 100;
1185 data->column_align[INDEX_SIZE] = COLUMN_ALIGN_RIGHT;
1186 data->column_clickable[INDEX_NAME] = TRUE;
1188 data->column_sortable[INDEX_NAME] = TRUE;
1189 data->column_sortable[INDEX_SIZE] = TRUE;
1190 data->column_sortable[INDEX_DATE] = TRUE;
1191 data->column_sortable[INDEX_TIME] = TRUE;
1193 data->sort_column = INDEX_NAME;
1194 data->sort_direction = SORT_DIRECTION_UP;
1195 data->sort_dirs = SORT_DRAWERS_FIRST;
1197 /* parse initial taglist */
1198 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
1200 switch (tag->ti_Tag)
1205 data->pool = CreatePool(0,4096,4096);
1206 if (!data->pool)
1208 CoerceMethod(cl,obj,OM_DISPOSE);
1209 return 0;
1212 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1213 data->ehn.ehn_Priority = 0;
1214 data->ehn.ehn_Flags = 0;
1215 data->ehn.ehn_Object = obj;
1216 data->ehn.ehn_Class = cl;
1218 data->thn.ihn_Flags = MUIIHNF_TIMER;
1219 data->thn.ihn_Method = MUIM_TextIconList_AutoScroll;
1220 data->thn.ihn_Object = obj;
1222 return (IPTR)obj;
1225 /**************************************************************************
1226 OM_DISPOSE
1227 **************************************************************************/
1228 static IPTR TextIconList_Dispose(struct IClass *cl, Object *obj, Msg msg)
1230 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1231 struct TextIconEntry *node;
1233 ForeachNode(&data->entries_list, node)
1237 if (data->pool) DeletePool(data->pool);
1239 DoSuperMethodA(cl,obj,msg);
1240 return 0;
1243 /**************************************************************************
1244 OM_SET
1245 **************************************************************************/
1246 static IPTR TextIconList_Set(struct IClass *cl, Object *obj, struct opSet *msg)
1248 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1249 struct TagItem *tag, *tags;
1250 LONG oldleft = data->view_x, oldtop = data->view_y;
1252 /* parse initial taglist */
1253 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
1255 switch (tag->ti_Tag)
1257 case MUIA_TextIconList_Left:
1258 if (data->view_x != (LONG)tag->ti_Data)
1260 LONG new_view_x = (LONG)tag->ti_Data;
1262 if (new_view_x + data->view_width > data->width)
1264 new_view_x = data->width - data->view_width;
1266 if (new_view_x < 0) new_view_x = 0;
1268 data->view_x = new_view_x;
1269 tag->ti_Data = new_view_x;
1271 break;
1273 case MUIA_TextIconList_Top:
1274 if (data->view_y != (LONG)tag->ti_Data)
1276 LONG new_view_y = (LONG)tag->ti_Data;
1278 if (new_view_y + data->view_height > data->height)
1280 new_view_y = data->height - data->view_height;
1282 if (new_view_y < 0) new_view_y = 0;
1284 data->view_y = new_view_y;
1285 tag->ti_Data = new_view_y;
1287 break;
1291 if ((oldleft != data->view_x) || (oldtop != data->view_y))
1293 data->update = UPDATE_SCROLL;
1294 data->update_scrolldx = data->view_x - oldleft;
1295 data->update_scrolldy = data->view_y - oldtop;
1297 MUI_Redraw(obj, MADF_DRAWUPDATE);
1300 return DoSuperMethodA(cl, obj, (Msg)msg);
1303 /**************************************************************************
1304 OM_GET
1305 **************************************************************************/
1306 static IPTR TextIconList_Get(struct IClass *cl, Object *obj, struct opGet *msg)
1308 /* small macro to simplify return value storage */
1309 #define STORE *(msg->opg_Storage)
1310 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1312 switch (msg->opg_AttrID)
1314 case MUIA_TextIconList_Left: STORE = data->view_x; return 1;
1315 case MUIA_TextIconList_Top: STORE = data->view_y; return 1;
1316 case MUIA_TextIconList_Width: STORE = data->width; return 1;
1317 case MUIA_TextIconList_Height: STORE = data->height; return 1;
1320 return DoSuperMethodA(cl, obj, (Msg) msg);
1321 #undef STORE
1324 /**************************************************************************
1325 MUIM_Setup
1326 **************************************************************************/
1327 static IPTR TextIconList_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
1329 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1330 LONG i;
1332 if (!DoSuperMethodA(cl, obj, (Msg) msg)) return 0;
1334 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1336 InitRastPort(&data->temprp);
1337 SetFont(&data->temprp, _font(obj));
1338 data->truecolor = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH) >= 15;
1340 data->lineheight = LINE_EXTRAHEIGHT + _font(obj)->tf_YSize;
1341 data->is_setup = TRUE;
1343 for(i = 0; i < NUM_COLORS; i++)
1345 data->colors[i].rgbpixel = rgb_colors[i];
1346 data->colors[i].pixel = data->colors[i].rgbpixel;
1348 if (!data->truecolor || !CyberGfxBase)
1350 ULONG r = (rgb_colors[i] & 0x00FF0000) >> 16;
1351 ULONG g = (rgb_colors[i] & 0x0000FF00) >> 8;
1352 ULONG b = (rgb_colors[i] & 0x000000FF);
1354 LONG pen = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,
1355 r * 0x01010101,
1356 g * 0x01010101,
1357 b * 0x01010101,
1358 OBP_FailIfBad, FALSE,
1359 OBP_Precision, PRECISION_GUI,
1360 TAG_DONE);
1362 if (pen >= 0)
1364 data->colors[i].pixel = pen;
1365 data->colors[i].alloced = TRUE;
1367 else
1369 data->colors[i].pixel = _pens(obj)[pen_colors[i]];
1370 data->colors[i].alloced = FALSE;
1375 if (data->show_header)
1377 data->headerheight = HEADERLINE_EXTRAHEIGHT + _font(obj)->tf_YSize;
1379 else
1381 data->headerheight = 0;
1384 if (data->num_entries)
1386 CalcAllEntryDimensions(data);
1387 CalcWidth(data);
1388 data->height = data->num_entries * data->lineheight;
1389 RecalcColumnMaxWidths(data);
1391 SetAttrs(obj, MUIA_TextIconList_Width, data->width,
1392 MUIA_TextIconList_Height, data->height,
1393 TAG_DONE);
1396 return 1;
1399 /**************************************************************************
1400 MUIM_Show
1401 **************************************************************************/
1402 static IPTR TextIconList_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
1404 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1405 LONG newleft, newtop;
1406 IPTR rc;
1408 rc = DoSuperMethodA(cl, obj, (Msg)msg);
1410 newleft = data->view_x;
1411 newtop = data->view_y;
1413 data->view_width = _mwidth(obj);
1414 data->view_height = _mheight(obj) - data->headerheight;
1416 SetAttrs(obj, MUIA_TextIconList_VisWidth, data->view_width,
1417 MUIA_TextIconList_VisHeight, data->view_height,
1418 TAG_DONE);
1420 data->view_rect.MinX = _mleft(obj);
1421 data->view_rect.MinY = _mtop(obj) + data->headerheight;
1422 data->view_rect.MaxX = _mright(obj);
1423 data->view_rect.MaxY = _mbottom(obj);
1425 data->header_rect.MinX = _mleft(obj);
1426 data->header_rect.MinY = _mtop(obj);
1427 data->header_rect.MaxX = _mright(obj);
1428 data->header_rect.MaxY = _mtop(obj) + data->headerheight - 1;
1430 if (newleft + data->view_width > data->width) newleft = data->width - data->view_width;
1431 if (newleft < 0) newleft = 0;
1433 if (newtop + data->view_height > data->height) newtop = data->height - data->view_height;
1434 if (newtop < 0) newtop = 0;
1436 if ((newleft != data->view_x) || (newtop != data->view_y))
1438 SetAttrs(obj, MUIA_TextIconList_Left, newleft,
1439 MUIA_TextIconList_Top, newtop,
1440 TAG_DONE);
1443 SetFont(_rp(obj), _font(obj));
1445 data->is_shown = TRUE;
1447 return rc;
1450 /**************************************************************************
1451 MUIM_Hide
1452 **************************************************************************/
1453 static IPTR TextIconList_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
1455 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1456 IPTR rc;
1458 data->is_shown = FALSE;
1460 rc = DoSuperMethodA(cl, obj, (Msg)msg);
1462 return rc;
1465 /**************************************************************************
1466 MUIM_Cleanup
1467 **************************************************************************/
1468 static IPTR TextIconList_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
1470 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1471 LONG i;
1473 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1475 DeinitRastPort(&data->temprp);
1477 for(i = 0; i < NUM_COLORS; i++)
1479 if (data->colors[i].alloced)
1481 ReleasePen(_screen(obj)->ViewPort.ColorMap, data->colors[i].pixel);
1482 data->colors[i].alloced = FALSE;
1486 data->is_setup = FALSE;
1488 return DoSuperMethodA(cl, obj, (Msg) msg);
1491 /**************************************************************************
1492 MUIM_AskMinMax
1493 **************************************************************************/
1494 static IPTR TextIconList_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
1496 ULONG rc = DoSuperMethodA(cl, obj, (Msg) msg);
1498 msg->MinMaxInfo->MinWidth += 10;
1499 msg->MinMaxInfo->MinHeight += 10;
1501 msg->MinMaxInfo->DefWidth += 100;
1502 msg->MinMaxInfo->DefHeight += 100;
1504 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
1505 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
1507 return rc;
1510 static void DrawHeaderLine(Object *obj, struct TextIconList_DATA *data)
1512 APTR clip;
1514 if (data->show_header && MustRenderRect(data, &data->header_rect))
1516 clip = MUI_AddClipping(muiRenderInfo(obj), data->header_rect.MinX,
1517 data->header_rect.MinY,
1518 data->header_rect.MaxX - data->header_rect.MinX + 1,
1519 data->header_rect.MaxY - data->header_rect.MinY + 1);
1521 RenderHeaderline(obj, data);
1523 MUI_RemoveClipping(muiRenderInfo(obj),clip);
1527 static void DrawLassoOutline(Object *obj, struct TextIconList_DATA *data)
1529 struct Rectangle lasso;
1531 GetAbsoluteLassoRect(data, &lasso);
1533 #if 1
1534 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MinY, lasso.MaxX, lasso.MinY, COLOR_SELECTED_BACKGROUND);
1535 MyRectFill(data, _rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1536 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1537 MyRectFill(data, _rp(obj), lasso.MinX, lasso.MinY, lasso.MinX, lasso.MaxY, COLOR_SELECTED_BACKGROUND);
1538 #else
1539 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_SHADOW], 0, JAM1);
1540 Move(_rp(obj), lasso.MinX, lasso.MinY);
1541 Draw(_rp(obj), lasso.MaxX, lasso.MinY);
1542 Draw(_rp(obj), lasso.MaxX, lasso.MaxY);
1543 Draw(_rp(obj), lasso.MinX, lasso.MaxY);
1544 Draw(_rp(obj), lasso.MinX, lasso.MinY);
1545 #endif
1548 /**************************************************************************
1549 MUIM_Draw
1550 **************************************************************************/
1551 static IPTR TextIconList_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
1553 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1554 APTR clip;
1555 struct TextIconEntry *entry;
1557 DoSuperMethodA(cl, obj, (Msg) msg);
1559 if (msg->flags & MADF_DRAWUPDATE)
1561 if (data->update == UPDATE_SCROLL)
1563 struct Region *region;
1564 struct Rectangle xrect, yrect;
1565 BOOL scroll_caused_damage;
1567 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
1569 data->update = 0;
1571 if ((abs(data->update_scrolldx) >= data->view_width) ||
1572 (abs(data->update_scrolldy) >= data->view_height))
1574 data->update = UPDATE_ALL;
1575 MUI_Redraw(obj, MADF_DRAWUPDATE);
1576 return 0;
1579 region = NewRegion();
1580 if (!region)
1582 data->update = UPDATE_ALL;
1583 MUI_Redraw(obj, MADF_DRAWUPDATE);
1584 return 0;
1587 if (data->update_scrolldx > 0)
1589 xrect.MinX = data->view_rect.MaxX - data->update_scrolldx;
1590 xrect.MinY = data->view_rect.MinY;
1591 xrect.MaxX = data->view_rect.MaxX;
1592 xrect.MaxY = data->view_rect.MaxY;
1594 OrRectRegion(region, &xrect);
1596 data->update_rect1 = &xrect;
1598 else if (data->update_scrolldx < 0)
1600 xrect.MinX = data->view_rect.MinX;
1601 xrect.MinY = data->view_rect.MinY;
1602 xrect.MaxX = data->view_rect.MinX - data->update_scrolldx;
1603 xrect.MaxY = data->view_rect.MaxY;
1605 OrRectRegion(region, &xrect);
1607 data->update_rect1 = &xrect;
1610 if (data->update_scrolldy > 0)
1612 yrect.MinX = data->view_rect.MinX;
1613 yrect.MinY = data->view_rect.MaxY - data->update_scrolldy;
1614 yrect.MaxX = data->view_rect.MaxX;
1615 yrect.MaxY = data->view_rect.MaxY;
1617 OrRectRegion(region, &yrect);
1619 data->update_rect2 = &yrect;
1621 else if (data->update_scrolldy < 0)
1623 yrect.MinX = data->view_rect.MinX;
1624 yrect.MinY = data->view_rect.MinY;
1625 yrect.MaxX = data->view_rect.MaxX;
1626 yrect.MaxY = data->view_rect.MinY - data->update_scrolldy;
1628 OrRectRegion(region, &yrect);
1630 data->update_rect2 = &yrect;
1633 ScrollRasterBF(_rp(obj),
1634 data->update_scrolldx,
1635 data->update_scrolldy,
1636 data->view_rect.MinX,
1637 data->view_rect.MinY,
1638 data->view_rect.MaxX,
1639 data->view_rect.MaxY);
1641 if (data->show_header && data->update_scrolldx)
1643 ScrollRasterBF(_rp(obj),
1644 data->update_scrolldx,
1646 data->header_rect.MinX,
1647 data->header_rect.MinY,
1648 data->header_rect.MaxX,
1649 data->header_rect.MaxY);
1652 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
1654 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1655 data->update = UPDATE_ALL;
1656 MUI_Redraw(obj, MADF_DRAWUPDATE);
1657 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1659 if (data->show_header && data->update_scrolldx)
1661 xrect.MinY = data->header_rect.MinY;
1662 xrect.MaxY = data->header_rect.MaxY;
1664 data->update_rect1 = &xrect;
1665 data->update_rect2 = NULL;
1667 clip = MUI_AddClipping(muiRenderInfo(obj), xrect.MinX,
1668 xrect.MinY,
1669 xrect.MaxX - xrect.MinX + 1,
1670 xrect.MaxY - xrect.MinY + 1);
1672 data->update = UPDATE_ALL;
1673 MUI_Redraw(obj, MADF_DRAWUPDATE);
1674 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1676 data->update_rect2 = NULL;
1680 data->update_rect1 = data->update_rect2 = NULL;
1681 data->update_scrolldx = data->update_scrolldy = 0;
1683 // DisposeRegion(region);
1685 if (scroll_caused_damage)
1687 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
1689 /* Theoretically it might happen that more damage is caused
1690 after ScrollRaster. By something else, like window movement
1691 in front of our window. Therefore refresh root object of
1692 window, not just this object */
1694 Object *o;
1696 get(_win(obj),MUIA_Window_RootObject, &o);
1697 MUI_Redraw(o, MADF_DRAWOBJECT);
1699 MUI_EndRefresh(muiRenderInfo(obj), 0);
1703 return 0;
1705 } /* if (data->update == UPDATE_SCROLL) */
1706 else if (data->update == UPDATE_DIRTY_ENTRIES)
1708 struct Region *clipregion;
1709 LONG first, numvisible, index = 0;
1711 data->update = 0;
1713 clipregion = NewRectRegion(data->view_rect.MinX,
1714 data->view_rect.MinY,
1715 data->view_rect.MaxX,
1716 data->view_rect.MaxY);
1718 if (clipregion)
1720 if (data->lasso_active)
1722 struct Rectangle lasso_rect;
1724 GetAbsoluteLassoRect(data, &lasso_rect);
1725 ClearRectRegion(clipregion, &lasso_rect);
1728 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1730 first = FirstVisibleLine(data);
1731 numvisible = NumVisibleLines(data);
1733 ForeachNode(&data->entries_list, entry)
1735 if (entry->dirty)
1737 if ((index >= first) && (index < first + numvisible))
1739 RenderEntry(obj, data, index);
1742 index++;
1745 if (data->lasso_active)
1747 struct Rectangle lasso_rect;
1748 struct Rectangle vis_lasso_rect;
1750 GetAbsoluteLassoRect(data, &lasso_rect);
1752 if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect))
1754 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1756 clipregion = NewRectRegion(vis_lasso_rect.MinX,
1757 vis_lasso_rect.MinY,
1758 vis_lasso_rect.MaxX,
1759 vis_lasso_rect.MaxY);
1761 data->lasso_paint = TRUE;
1763 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1765 index = 0;
1766 ForeachNode(&data->entries_list, entry)
1768 if (entry->dirty)
1770 if ((index >= first) && (index < first + numvisible))
1772 RenderEntry(obj, data, index);
1775 index++;
1778 data->lasso_paint = FALSE;
1780 DrawLassoOutline(obj, data);
1782 } /* if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect)) */
1784 } /* if (data->lasso_active) */
1786 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1788 ForeachNode(&data->entries_list, entry)
1790 if (entry->dirty) entry->dirty = FALSE;
1792 return 0;
1795 } /* else if (data->update == UPDATE_DIRTY_ENTRIES) */
1796 else if (data->update == UPDATE_HEADER)
1798 data->update = 0;
1800 DrawHeaderLine(obj, data);
1802 return 0;
1805 } /* if (msg->flags & MADF_DRAWUPDATE) */
1807 if (MustRenderRect(data, &data->view_rect))
1809 struct Region *clipregion;
1811 clipregion = NewRectRegion(data->view_rect.MinX,
1812 data->view_rect.MinY,
1813 data->view_rect.MaxX,
1814 data->view_rect.MaxY);
1816 if (clipregion)
1818 if (data->lasso_active)
1820 struct Rectangle lasso_rect;
1822 GetAbsoluteLassoRect(data, &lasso_rect);
1823 ClearRectRegion(clipregion, &lasso_rect);
1826 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1828 RenderAllEntries(obj, data);
1830 if (data->lasso_active)
1832 struct Rectangle lasso_rect;
1833 struct Rectangle vis_lasso_rect;
1835 GetAbsoluteLassoRect(data, &lasso_rect);
1837 if (AndRectRect(&data->view_rect, &lasso_rect, &vis_lasso_rect))
1839 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1841 clipregion = NewRectRegion(vis_lasso_rect.MinX,
1842 vis_lasso_rect.MinY,
1843 vis_lasso_rect.MaxX,
1844 vis_lasso_rect.MaxY);
1846 data->lasso_paint = TRUE;
1848 clip = MUI_AddClipRegion(muiRenderInfo(obj), clipregion);
1850 RenderAllEntries(obj, data);
1852 data->lasso_paint = FALSE;
1854 DrawLassoOutline(obj, data);
1859 MUI_RemoveClipRegion(muiRenderInfo(obj),clip);
1861 } /* if (clipregion) */
1863 } /* if (MustRenderRect(data, &data->view_rect)) */
1865 DrawHeaderLine(obj, data);
1867 data->update = 0;
1869 return 0;
1872 /**************************************************************************
1873 MUIM_Draw
1874 **************************************************************************/
1875 static IPTR TextIconList_AutoScroll(struct IClass *cl, Object *obj, Msg msg)
1877 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1879 if (data->lasso_active)
1881 LONG new_view_x, new_view_y;
1883 new_view_x = data->view_x;
1884 new_view_y = data->view_y;
1886 if (data->click_x < data->view_rect.MinX)
1888 new_view_x -= (data->view_rect.MinX - data->click_x) / 4;
1890 else if (data->click_x > data->view_rect.MaxX)
1892 new_view_x += (data->click_x - data->view_rect.MaxX) / 4;
1895 if (data->click_y < data->view_rect.MinY)
1897 new_view_y -= (data->view_rect.MinY - data->click_y) / 4;
1899 else if (data->click_y > data->view_rect.MaxY)
1901 new_view_y += (data->click_y - data->view_rect.MaxY) / 4;
1904 if (new_view_x + data->view_width > data->width)
1906 new_view_x = data->width - data->view_width;
1908 if (new_view_x < 0) new_view_x = 0;
1910 if (new_view_y + data->view_height > data->height)
1912 new_view_y = data->height - data->view_height;
1914 if (new_view_y < 0) new_view_y = 0;
1916 if ((new_view_x != data->view_x) || (new_view_y != data->view_y))
1918 data->old_lasso_rect = data->lasso_rect;
1920 data->lasso_rect.MaxX += new_view_x - data->view_x;
1921 data->lasso_rect.MaxY += new_view_y - data->view_y;
1923 RethinkLasso(obj, data);
1925 SetAttrs(obj, MUIA_TextIconList_Left, new_view_x,
1926 MUIA_TextIconList_Top, new_view_y,
1927 TAG_DONE);
1931 else
1933 DisableAutoScrollTimer(obj, data);
1936 return 0;
1939 /**************************************************************************
1940 MUIM_HandleEvent
1941 **************************************************************************/
1942 static IPTR TextIconList_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
1944 struct TextIconList_DATA *data = INST_DATA(cl, obj);
1945 IPTR retval = 0;
1947 if (msg->imsg)
1949 LONG mx = msg->imsg->MouseX;
1950 LONG my = msg->imsg->MouseY;
1951 LONG line, col;
1952 BOOL shift_qual;
1954 shift_qual = (msg->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? TRUE : FALSE;
1956 switch (msg->imsg->Class)
1958 case IDCMP_MOUSEBUTTONS:
1959 switch(msg->imsg->Code)
1961 case SELECTDOWN:
1962 //kprintf("SELECTDOWN\n");
1963 if (data->inputstate == INPUTSTATE_NONE)
1965 if ( ((line = LineUnderMouse(data, mx, my)) >= 0) &&
1966 ((col = ColumnUnderMouse(data, mx, my)) >= 0) )
1968 //kprintf("click on line %d col %d\n", line, col);
1970 if (data->column_clickable[col])
1972 if (data->active_entry != line)
1974 struct TextIconEntry *old, *new;
1976 old = GetEntryFromIndex(data, data->active_entry);
1977 new = GetEntryFromIndex(data, line);
1979 data->active_entry = line;
1980 if (old && old->selected && !shift_qual)
1982 Remove((struct Node *)&old->selection_node);
1983 old->selected = FALSE;
1984 old->dirty = TRUE;
1986 data->num_selected--;
1989 if (!shift_qual && data->num_selected)
1991 struct TextIconEntry *entry;
1993 ForeachNode(&data->entries_list, entry)
1995 if (entry->selected)
1997 Remove((struct Node *)&entry->selection_node);
1998 entry->selected = FALSE;
1999 entry->dirty = TRUE;
2003 data->num_selected = 0;
2006 if (new && !new->selected)
2008 AddTail((struct List *)&data->selection_list, (struct Node *)&new->selection_node);
2009 new->selected = TRUE;
2010 new->dirty = TRUE;
2012 data->num_selected++;
2015 data->update = UPDATE_DIRTY_ENTRIES;
2016 MUI_Redraw(obj, MADF_DRAWUPDATE);
2018 } /* if (data->active_entry != line) */
2020 } /* if (data->column_clickable[col]) */
2021 else
2023 if (!shift_qual && data->num_selected)
2025 struct TextIconEntry *entry;
2027 ForeachNode(&data->entries_list, entry)
2029 if (entry->selected)
2031 Remove((struct Node *)&entry->selection_node);
2032 entry->selected = FALSE;
2033 entry->dirty = TRUE;
2037 data->num_selected = 0;
2038 data->update = UPDATE_DIRTY_ENTRIES;
2039 MUI_Redraw(obj, MADF_DRAWUPDATE);
2042 data->lasso_rect.MinX = mx - data->view_rect.MinX + data->view_x;
2043 data->lasso_rect.MinY = my - data->view_rect.MinY + data->view_y;
2044 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
2045 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
2047 data->inputstate = INPUTSTATE_LASSO;
2048 data->lasso_active = TRUE;
2050 data->click_x = mx;
2051 data->click_y = my;
2053 EnableMouseMoveEvents(obj, data);
2056 } /* if click on entry */
2057 else if ((col = ColumnResizeHandleUnderMouse(data, mx, my)) >= 0)
2059 data->inputstate = INPUTSTATE_COL_RESIZE;
2060 data->click_column = col;
2061 data->click_x = mx - data->column_width[col];
2063 EnableMouseMoveEvents(obj, data);
2065 } /* else if click on column header entry resize handle */
2066 else if ((col = ColumnHeaderUnderMouse(data, mx, my)) >= 0)
2068 data->inputstate = INPUTSTATE_COL_HEADER_CLICK;
2069 data->click_column = col;
2070 data->click_x = mx;
2071 data->click_y = my;
2073 EnableMouseMoveEvents(obj, data);
2075 data->update = UPDATE_HEADER;
2076 MUI_Redraw(obj, MADF_DRAWUPDATE);
2079 } /* if (data->inputstate == INPUTSTATE_NONE) */
2080 break;
2082 case SELECTUP:
2083 if (data->inputstate == INPUTSTATE_COL_RESIZE)
2085 DisableMouseMoveEvents(obj, data);
2087 data->inputstate = INPUTSTATE_NONE;
2089 else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK)
2091 DisableMouseMoveEvents(obj, data);
2093 data->inputstate = INPUTSTATE_NONE;
2095 if (ColumnHeaderUnderMouse(data, data->click_x, data->click_y) == data->click_column)
2098 if (data->column_sortable[data->click_column])
2100 if (data->sort_column == data->click_column)
2102 data->sort_direction = 1 - data->sort_direction;
2104 else
2106 data->sort_direction = SORT_DIRECTION_UP;
2107 data->sort_column = data->click_column;
2110 ReSortEntries(data);
2112 data->update = UPDATE_ALL;
2113 MUI_Redraw(obj, MADF_DRAWUPDATE);
2116 else
2118 data->update = UPDATE_HEADER;
2119 MUI_Redraw(obj, MADF_DRAWUPDATE);
2122 } /* mouse still over column header */
2124 } /* else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK) */
2125 else if (data->inputstate == INPUTSTATE_LASSO)
2127 DisableMouseMoveEvents(obj, data);
2128 DisableAutoScrollTimer(obj, data);
2130 data->inputstate = INPUTSTATE_NONE;
2131 data->lasso_active = FALSE;
2133 data->update = UPDATE_ALL;
2134 MUI_Redraw(obj, MADF_DRAWUPDATE);
2136 break;
2138 case MIDDLEDOWN:
2139 if (data->inputstate == INPUTSTATE_NONE)
2141 data->inputstate = INPUTSTATE_PAN;
2143 data->click_x = mx - data->view_rect.MinX + data->view_x;
2144 data->click_y = my - data->view_rect.MinY + data->view_y;
2146 EnableMouseMoveEvents(obj, data);
2149 break;
2151 case MIDDLEUP:
2152 if (data->inputstate == INPUTSTATE_PAN)
2154 DisableMouseMoveEvents(obj, data);
2156 data->inputstate = INPUTSTATE_NONE;
2158 break;
2160 } /* switch(msg->imsg->Code) */
2161 break;
2163 case IDCMP_MOUSEMOVE:
2164 if (data->inputstate == INPUTSTATE_PAN)
2166 LONG new_view_x, new_view_y;
2168 new_view_x = data->click_x - (mx - data->view_rect.MinX);
2169 new_view_y = data->click_y - (my - data->view_rect.MinY);
2171 if (new_view_x + data->view_width > data->width)
2173 new_view_x = data->width - data->view_width;
2175 if (new_view_x < 0) new_view_x = 0;
2177 if (new_view_y + data->view_height > data->height)
2179 new_view_y = data->height - data->view_height;
2181 if (new_view_y < 0) new_view_y = 0;
2183 if ((new_view_x != data->view_x) || (new_view_y != data->view_y))
2185 SetAttrs(obj, MUIA_TextIconList_Left, new_view_x,
2186 MUIA_TextIconList_Top, new_view_y,
2187 TAG_DONE);
2190 } /* if (data->inputstate == INPUTSTATE_PAN) */
2191 else if (data->inputstate == INPUTSTATE_COL_RESIZE)
2193 LONG act_colwidth = data->column_width[data->click_column];
2194 LONG new_colwidth = mx - data->click_x;
2196 if (new_colwidth < MIN_COLUMN_WIDTH) new_colwidth = MIN_COLUMN_WIDTH;
2198 if (new_colwidth > act_colwidth)
2200 data->column_width[data->click_column] = new_colwidth;
2201 data->width += new_colwidth - act_colwidth;
2202 data->update = UPDATE_ALL;
2203 MUI_Redraw(obj, MADF_DRAWUPDATE);
2205 set(obj, MUIA_TextIconList_Width, data->width);
2207 else if (new_colwidth < act_colwidth)
2209 BOOL scroll_left = FALSE;
2211 data->column_width[data->click_column] = new_colwidth;
2212 data->width += new_colwidth - act_colwidth;
2214 if (data->view_x + data->view_width > data->width)
2216 LONG new_view_x = data->width - data->view_width;
2218 if (new_view_x < 0) new_view_x = 0;
2219 if (new_view_x != data->view_x)
2221 scroll_left = TRUE;
2222 data->view_x = new_view_x;
2226 data->update = UPDATE_ALL;
2227 MUI_Redraw(obj, MADF_DRAWUPDATE);
2229 SetAttrs(obj, scroll_left ? MUIA_TextIconList_Left : TAG_IGNORE, data->view_x,
2230 MUIA_TextIconList_Width, data->width,
2231 TAG_DONE);
2233 } /* else if (new_colwidth < act_colwidth) */
2235 } /* else if (data->inputstate == INPUTSTATE_COL_RESIZE) */
2236 else if (data->inputstate == INPUTSTATE_COL_HEADER_CLICK)
2238 BOOL old = ColumnHeaderUnderMouse(data, data->click_x, data->click_y);
2239 BOOL new = ColumnHeaderUnderMouse(data, mx, my);
2241 if (new != old)
2243 data->click_x = mx;
2244 data->click_y = my;
2245 data->update = UPDATE_HEADER;
2246 MUI_Redraw(obj, MADF_DRAWUPDATE);
2249 else if (data->inputstate == INPUTSTATE_LASSO)
2251 struct Rectangle old_lasso, new_lasso;
2252 struct Region *region;
2253 APTR clip;
2255 data->click_x = mx;
2256 data->click_y = my;
2258 data->old_lasso_rect = data->lasso_rect;
2259 GetAbsoluteLassoRect(data, &old_lasso);
2260 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
2261 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
2262 GetAbsoluteLassoRect(data, &new_lasso);
2264 region = NewRectRegion(new_lasso.MinX, new_lasso.MinY, new_lasso.MaxX, new_lasso.MaxY);
2265 if (region)
2267 struct Rectangle render_range;
2269 XorRectRegion(region, &old_lasso);
2270 OrRectOutlineRegion(region, &old_lasso);
2271 OrRectOutlineRegion(region, &new_lasso);
2273 render_range = region->bounds;
2275 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
2277 data->update = UPDATE_ALL;
2278 data->update_rect1 = &render_range;
2279 MUI_Redraw(obj, MADF_DRAWUPDATE);
2280 data->update_rect1 = 0;
2282 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
2285 RethinkLasso(obj, data);
2287 if ((mx >= data->view_rect.MinX) &&
2288 (my >= data->view_rect.MinY) &&
2289 (mx <= data->view_rect.MaxX) &&
2290 (my <= data->view_rect.MaxY))
2292 DisableAutoScrollTimer(obj, data);
2294 else
2296 EnableAutoScrollTimer(obj, data);
2301 break;
2303 } /* switch (msg->imsg->Class) */
2305 } /* if (msg->imsg) */
2307 return retval;
2311 /**************************************************************************
2312 MUIM_TextIconList_Clear
2313 **************************************************************************/
2314 static IPTR TextIconList_Clear(struct IClass *cl, Object *obj, struct MUIP_TextIconList_Clear *msg)
2316 struct TextIconList_DATA *data = INST_DATA(cl, obj);
2317 struct TextIconEntry *node;
2318 LONG i;
2320 while ((node = (struct TextIconEntry *)RemTail((struct List *)&data->entries_list)))
2322 FreePooled(data->pool,node,sizeof(*node));
2324 NewList((struct List *)&data->selection_list);
2326 data->view_x = data->view_y = data->width = data->height = 0;
2327 data->num_entries = 0;
2328 data->active_entry = -1;
2329 data->num_selected = 0;
2332 for(i = 0; i < NUM_COLUMNS; i++)
2334 data->column_maxwidth[i] = 0;
2337 SetAttrs(obj, MUIA_TextIconList_Left, data->view_x,
2338 MUIA_TextIconList_Top, data->view_y,
2339 MUIA_TextIconList_Width, data->width,
2340 MUIA_TextIconList_Height, data->height,
2341 TAG_DONE);
2343 data->update = UPDATE_ALL;
2344 MUI_Redraw(obj,MADF_DRAWUPDATE);
2345 return 1;
2348 /**************************************************************************
2349 MUIM_TextIconList_Add.
2350 Returns 0 on failure otherwise 1
2351 **************************************************************************/
2352 static IPTR TextIconList_Add(struct IClass *cl, Object *obj, struct MUIP_TextIconList_Add *msg)
2354 struct TextIconList_DATA *data = INST_DATA(cl, obj);
2355 struct TextIconEntry *entry;
2356 struct DateTime dt;
2357 UBYTE *sp;
2359 if (!(entry = AllocPooled(data->pool,sizeof(struct TextIconEntry))))
2361 return 0;
2364 memset(entry, 0, sizeof(struct TextIconEntry));
2366 entry->fib = *msg->fib;
2368 if (entry->fib.fib_DirEntryType > 0)
2370 strcpy(GetTextIconEntryText(data, entry, INDEX_SIZE), "Drawer");
2372 else
2374 sprintf(GetTextIconEntryText(data, entry, INDEX_SIZE), "%ld", entry->fib.fib_Size);
2377 dt.dat_Stamp = entry->fib.fib_Date;
2378 dt.dat_Format = FORMAT_DOS;
2379 dt.dat_Flags = 0;
2380 dt.dat_StrDay = NULL;
2381 dt.dat_StrDate = GetTextIconEntryText(data, entry, INDEX_DATE);
2382 dt.dat_StrTime = GetTextIconEntryText(data, entry, INDEX_TIME);;
2384 DateToStr(&dt);
2386 sp = GetTextIconEntryText(data, entry, INDEX_PROTECTION);
2387 *sp++ = (entry->fib.fib_Protection & FIBF_SCRIPT) ? 's' : '-';
2388 *sp++ = (entry->fib.fib_Protection & FIBF_PURE) ? 'p' : '-';
2389 *sp++ = (entry->fib.fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
2390 *sp++ = (entry->fib.fib_Protection & FIBF_READ) ? '-' : 'r';
2391 *sp++ = (entry->fib.fib_Protection & FIBF_WRITE) ? '-' : 'w';
2392 *sp++ = (entry->fib.fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
2393 *sp++ = (entry->fib.fib_Protection & FIBF_DELETE) ? '-' : 'd';
2394 *sp++ = '\0';
2396 data->num_entries++;
2398 SortInNode(data, (struct List *)&data->entries_list, (struct Node *)entry, (APTR)CompareNodes);
2400 if (data->is_setup)
2402 CalcEntryDimension(data, entry);
2403 data->height += data->lineheight;
2405 CalcWidth(data);
2407 SetAttrs(obj, MUIA_TextIconList_Width, data->width,
2408 MUIA_TextIconList_Height, data->height,
2409 TAG_DONE);
2412 return 1;
2415 BOOPSI_DISPATCHER(IPTR,TextIconList_Dispatcher, cl, obj, msg)
2417 switch (msg->MethodID)
2420 case OM_NEW: return TextIconList_New(cl, obj, (struct opSet *)msg);
2421 case OM_DISPOSE: return TextIconList_Dispose(cl,obj, msg);
2422 case OM_SET: return TextIconList_Set(cl,obj,(struct opSet *)msg);
2423 case OM_GET: return TextIconList_Get(cl,obj,(struct opGet *)msg);
2424 case MUIM_Setup: return TextIconList_Setup(cl,obj,(struct MUIP_Setup *)msg);
2425 case MUIM_Show: return TextIconList_Show(cl,obj,(struct MUIP_Show *)msg);
2426 case MUIM_Hide: return TextIconList_Hide(cl,obj,(struct MUIP_Hide *)msg);
2427 case MUIM_Cleanup: return TextIconList_Cleanup(cl,obj,(struct MUIP_Cleanup *)msg);
2428 case MUIM_AskMinMax: return TextIconList_AskMinMax(cl,obj,(struct MUIP_AskMinMax *)msg);
2429 case MUIM_Draw: return TextIconList_Draw(cl,obj,(struct MUIP_Draw *)msg);
2430 // case MUIM_Layout: return TextIconList_Layout(cl,obj,(struct MUIP_Layout *)msg);
2431 case MUIM_HandleEvent: return TextIconList_HandleEvent(cl,obj,(struct MUIP_HandleEvent *)msg);
2432 // case MUIM_CreateDragImage: return TextIconList_CreateDragImage(cl,obj,(APTR)msg);
2433 // case MUIM_DeleteDragImage: return TextIconList_DeleteDragImage(cl,obj,(APTR)msg);
2434 // case MUIM_DragQuery: return TextIconList_DragQuery(cl,obj,(APTR)msg);
2435 // case MUIM_DragReport: return TextIconList_DragReport(cl,obj,(APTR)msg);
2436 // case MUIM_DragDrop: return TextIconList_DragDrop(cl,obj,(APTR)msg);
2438 // case MUIM_TextIconList_Update: return TextIconList_Update(cl,obj,(APTR)msg);
2439 case MUIM_TextIconList_Clear: return TextIconList_Clear(cl,obj,(APTR)msg);
2440 case MUIM_TextIconList_Add: return TextIconList_Add(cl,obj,(APTR)msg);
2441 // case MUIM_TextIconList_NextSelected: return TextIconList_NextSelected(cl,obj,(APTR)msg);
2442 // case MUIM_TextIconList_UnselectAll: return TextIconList_UnselectAll(cl,obj,(APTR)msg);
2444 case MUIM_TextIconList_AutoScroll: return TextIconList_AutoScroll(cl,obj,(APTR)msg);
2447 return DoSuperMethodA(cl, obj, msg);
2449 BOOPSI_DISPATCHER_END
2451 /*================ TextIconListview class ===================*/
2453 #define MUIB_TextIconListview (MUIB_AROS | 0x00000800)
2455 #define MUIA_TextIconListview_TextIconList (MUIB_TextIconListview | 0x00000000)
2456 #define MUIA_TextIconListview_UseWinBorder (MUIB_TextIconListview | 0x00000001)
2458 #define TextIconListviewObject BOOPSIOBJMACRO_START(CL_TextIconListview->mcc_Class)
2460 struct TextIconListview_DATA
2462 Object *texticonlist;
2463 Object *vert, *horiz, *button;
2464 struct Hook hook;
2465 struct Hook layout_hook;
2469 IPTR TextIconListview_Layout_Function(struct Hook *hook, Object *obj, struct MUI_LayoutMsg *lm)
2471 struct TextIconListview_DATA *data = (struct TextIconListview_DATA *)hook->h_Data;
2473 switch (lm->lm_Type)
2475 case MUILM_MINMAX:
2477 /* Calulate the minmax dimension of the group,
2478 ** We only have a fixed number of children, so we need no NextObject()
2480 WORD maxxxxwidth = 0;
2481 WORD maxxxxheight = 0;
2483 maxxxxwidth = _minwidth(data->texticonlist) + _minwidth(data->vert);
2484 if (_minwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _minwidth(data->horiz);
2485 lm->lm_MinMax.MinWidth = maxxxxwidth;
2487 maxxxxheight = _minheight(data->texticonlist) + _minheight(data->horiz);
2488 if (_minheight(data->vert) > maxxxxheight) maxxxxheight = _minheight(data->vert);
2489 lm->lm_MinMax.MinHeight = maxxxxheight;
2491 maxxxxwidth = _defwidth(data->texticonlist) + _defwidth(data->vert);
2492 if (_defwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _defwidth(data->horiz);
2493 lm->lm_MinMax.DefWidth = maxxxxwidth;
2495 maxxxxheight = _defheight(data->texticonlist) + _defheight(data->horiz);
2496 if (_defheight(data->vert) > maxxxxheight) maxxxxheight = _defheight(data->vert);
2497 lm->lm_MinMax.DefHeight = maxxxxheight;
2499 lm->lm_MinMax.MaxWidth = MUI_MAXMAX;
2500 lm->lm_MinMax.MaxHeight = MUI_MAXMAX;
2502 return 0;
2505 case MUILM_LAYOUT:
2507 /* Now place the objects between (0,0,lm->lm_Layout.Width-1,lm->lm_Layout.Height-1)
2510 LONG virt_width;
2511 LONG virt_height;
2512 LONG vert_width = _minwidth(data->vert);
2513 LONG horiz_height = _minheight(data->horiz);
2514 LONG lay_width = lm->lm_Layout.Width;
2515 LONG lay_height = lm->lm_Layout.Height;
2516 LONG cont_width;
2517 LONG cont_height;
2519 /* layout the virtual group a first time, to determine the virtual width/height */
2520 MUI_Layout(data->texticonlist,0,0,lay_width,lay_height,0);
2522 get(data->texticonlist, MUIA_TextIconList_Width, &virt_width);
2523 get(data->texticonlist, MUIA_TextIconList_Height, &virt_height);
2525 virt_width += _subwidth(data->texticonlist);
2526 virt_height += _subheight(data->texticonlist);
2528 if (virt_width > lay_width && virt_height > lay_height)
2530 /* We need all scrollbars and the button */
2531 set(data->vert, MUIA_ShowMe, TRUE); /* We could also overload MUIM_Show... */
2532 set(data->horiz, MUIA_ShowMe, TRUE);
2533 set(data->button, MUIA_ShowMe, TRUE);
2534 cont_width = lay_width - vert_width;
2535 cont_height = lay_height - horiz_height;
2536 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
2537 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
2538 MUI_Layout(data->button, cont_width, cont_height, vert_width, horiz_height, 0);
2539 } else
2541 if (virt_height > lay_height)
2543 set(data->vert, MUIA_ShowMe, TRUE);
2544 set(data->horiz, MUIA_ShowMe, FALSE);
2545 set(data->button, MUIA_ShowMe, FALSE);
2547 cont_width = lay_width - vert_width;
2548 cont_height = lay_height;
2549 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
2550 } else
2552 if (virt_width > lay_width)
2554 set(data->vert, MUIA_ShowMe, FALSE);
2555 set(data->horiz, MUIA_ShowMe, TRUE);
2556 set(data->button, MUIA_ShowMe, FALSE);
2558 cont_width = lay_width;
2559 cont_height = lay_height - horiz_height;
2560 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
2561 } else
2563 set(data->vert, MUIA_ShowMe, FALSE);
2564 set(data->horiz, MUIA_ShowMe, FALSE);
2565 set(data->button, MUIA_ShowMe, FALSE);
2567 cont_width = lay_width;
2568 cont_height = lay_height;
2573 /* Layout the group a second time, note that setting _mwidth() and _mheight() should be enough, or we invent a new flag */
2574 MUI_Layout(data->texticonlist,0,0,cont_width,cont_height,0);
2575 return 1;
2578 return 0;
2582 IPTR TextIconListview_Function(struct Hook *hook, APTR dummyobj, void **msg)
2584 struct TextIconListview_DATA *data = (struct TextIconListview_DATA *)hook->h_Data;
2585 int type = (int)msg[0];
2586 LONG val = (LONG)msg[1];
2588 switch (type)
2590 case 1:
2592 get(data->vert,MUIA_Prop_First,&val);
2593 SetAttrs(data->texticonlist,MUIA_TextIconList_Top, val, MUIA_NoNotify, TRUE, TAG_DONE);
2594 break;
2597 case 2:
2599 get(data->horiz,MUIA_Prop_First,&val);
2600 SetAttrs(data->texticonlist,MUIA_TextIconList_Left, val, MUIA_NoNotify, TRUE, TAG_DONE);
2601 break;
2603 case 3: nnset(data->horiz, MUIA_Prop_First, val); break;
2604 case 4: nnset(data->vert, MUIA_Prop_First, val); break;
2606 return 0;
2610 IPTR TextIconListview__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2612 struct TextIconListview_DATA *data;
2613 //struct TagItem *tags,*tag;
2614 Object *texticonlist = (Object*)GetTagData(MUIA_TextIconListview_TextIconList, 0, msg->ops_AttrList);
2615 Object *vert,*horiz,*button,*group;
2617 int usewinborder;
2619 usewinborder = GetTagData(MUIA_TextIconListview_UseWinBorder, FALSE, msg->ops_AttrList);
2621 if (!usewinborder) button = ScrollbuttonObject, End;
2622 else button = NULL;
2624 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
2625 MUIA_Group_Horiz, FALSE,
2626 Child, (IPTR) (group = GroupObject,
2627 Child, (IPTR) texticonlist,
2628 Child, (IPTR) (vert = ScrollbarObject,
2629 usewinborder ? MUIA_Prop_UseWinBorder : TAG_IGNORE, MUIV_Prop_UseWinBorder_Right,
2630 MUIA_Prop_DeltaFactor, 20,
2631 MUIA_Group_Horiz, FALSE,
2632 End),
2633 Child, (IPTR) (horiz = ScrollbarObject,
2634 usewinborder?MUIA_Prop_UseWinBorder:TAG_IGNORE, MUIV_Prop_UseWinBorder_Bottom,
2635 MUIA_Prop_DeltaFactor, 20,
2636 MUIA_Group_Horiz, TRUE,
2637 End),
2638 usewinborder ? TAG_IGNORE : Child, (IPTR) button,
2639 End),
2640 TAG_DONE);
2642 if (!obj)
2644 return 0;
2647 data = INST_DATA(cl, obj);
2648 data->vert = vert;
2649 data->horiz = horiz;
2650 data->button = button;
2651 data->texticonlist = texticonlist;
2653 if (!usewinborder)
2655 data->layout_hook.h_Entry = HookEntry;
2656 data->layout_hook.h_SubEntry = (HOOKFUNC)TextIconListview_Layout_Function;
2657 data->layout_hook.h_Data = data;
2659 SetAttrs(group, MUIA_Group_Forward, FALSE,
2660 MUIA_Group_LayoutHook, (IPTR) &data->layout_hook,
2661 TAG_DONE);
2664 data->hook.h_Entry = HookEntry;
2665 data->hook.h_SubEntry = (HOOKFUNC)TextIconListview_Function;
2666 data->hook.h_Data = data;
2668 DoMethod(vert, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 1, MUIV_TriggerValue);
2669 DoMethod(horiz, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 2, MUIV_TriggerValue);
2670 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Left, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 3, MUIV_TriggerValue);
2671 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Top, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 4, MUIV_TriggerValue);
2672 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Width, MUIV_EveryTime, (IPTR)horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
2673 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_Height, MUIV_EveryTime, (IPTR)vert, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
2674 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_VisWidth, MUIV_EveryTime, (IPTR)horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
2675 DoMethod(texticonlist, MUIM_Notify, MUIA_TextIconList_VisHeight, MUIV_EveryTime, (IPTR)vert, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
2677 return (IPTR)obj;
2681 IPTR TextIconListview__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2683 //struct TextIconListview_DATA *data = INST_DATA(cl, obj);
2685 return DoSuperMethodA(cl,obj,msg);
2688 IPTR TextIconListview__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
2690 struct TextIconListview_DATA *data = INST_DATA(cl, obj);
2691 IPTR top,left,width,height,viswidth,visheight;
2693 get(data->texticonlist, MUIA_TextIconList_Left, &left);
2694 get(data->texticonlist, MUIA_TextIconList_Top, &top);
2695 get(data->texticonlist, MUIA_TextIconList_Width, &width);
2696 get(data->texticonlist, MUIA_TextIconList_Height, &height);
2697 get(data->texticonlist, MUIA_TextIconList_VisWidth, &viswidth);
2698 get(data->texticonlist, MUIA_TextIconList_VisHeight, &visheight);
2700 SetAttrs(data->horiz, MUIA_Prop_First, left,
2701 MUIA_Prop_Entries, width,
2702 MUIA_Prop_Visible, viswidth,
2703 TAG_DONE);
2706 SetAttrs(data->vert, MUIA_Prop_First, top,
2707 MUIA_Prop_Entries, height,
2708 MUIA_Prop_Visible, visheight,
2709 TAG_DONE);
2711 return DoSuperMethodA(cl,obj,(Msg)msg);
2714 BOOPSI_DISPATCHER(IPTR,TextIconListview_Dispatcher, cl, obj, msg)
2716 switch (msg->MethodID)
2718 case OM_NEW: return TextIconListview__OM_NEW(cl, obj, (struct opSet *) msg);
2719 case OM_DISPOSE: return TextIconListview__OM_DISPOSE(cl, obj, msg);
2720 case MUIM_Show: return TextIconListview__MUIM_Show(cl, obj, (struct MUIP_Show*)msg);
2723 return DoSuperMethodA(cl, obj, msg);
2726 BOOPSI_DISPATCHER_END
2729 int main(void)
2731 Object *wnd, *texticonlist;
2732 #if 0
2733 Object *iconlist;
2734 #endif
2736 MUIMasterBase = (struct Library*)OpenLibrary("muimaster.library",0);
2738 CL_TextIconListview = MUI_CreateCustomClass(NULL,MUIC_Group,NULL,sizeof(struct TextIconListview_DATA), TextIconListview_Dispatcher);
2739 CL_TextIconList = MUI_CreateCustomClass(NULL,MUIC_Area,NULL,sizeof(struct TextIconList_DATA), TextIconList_Dispatcher);
2741 app = ApplicationObject,
2742 SubWindow, (IPTR) (wnd = WindowObject,
2743 MUIA_Window_Title, (IPTR) "texticonlist",
2744 MUIA_Window_Activate, TRUE,
2746 WindowContents, (IPTR) VGroup,
2747 MUIA_Background, MUII_GroupBack,
2748 #if 0
2749 Child, (IPTR) IconListviewObject,
2750 MUIA_IconListview_IconList, (IPTR) (iconlist = IconDrawerListObject,
2751 InputListFrame,
2752 MUIA_IconDrawerList_Drawer, (IPTR) "C:",
2753 End),
2754 End,
2755 #endif
2756 Child, (IPTR) TextIconListviewObject,
2757 // MUIA_TextIconListview_UseWinBorder, TRUE,
2758 MUIA_TextIconListview_TextIconList, (IPTR) (texticonlist = TextIconListObject,
2759 InputListFrame,
2760 InnerSpacing(0,0),
2761 End),
2762 End,
2765 Child, (IPTR) (texticonlist = TextIconListObject, InputListFrame, End),
2767 End,
2768 End),
2769 End;
2771 if (app)
2773 ULONG sigs = 0;
2775 DoMethod
2777 wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, (IPTR) app,
2778 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit
2782 BPTR lock = Lock("C:", SHARED_LOCK);
2784 if (lock)
2786 struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, NULL);
2787 if (fib)
2789 if (Examine(lock, fib))
2791 while(ExNext(lock, fib))
2793 DoMethod(texticonlist, MUIM_TextIconList_Add, (IPTR) fib);
2797 FreeDosObject(DOS_FIB, fib);
2800 UnLock(lock);
2804 set(wnd,MUIA_Window_Open,TRUE);
2805 #if 0
2806 set(iconlist, MUIA_IconDrawerList_Drawer, "C:");
2807 #endif
2809 while (DoMethod(app, MUIM_Application_NewInput, (IPTR) &sigs) != MUIV_Application_ReturnID_Quit)
2811 if (sigs)
2813 sigs = Wait(sigs | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
2814 if (sigs & SIGBREAKF_CTRL_C) break;
2815 if (sigs & SIGBREAKF_CTRL_D) break;
2819 MUI_DisposeObject(app);
2822 MUI_DeleteCustomClass(CL_TextIconList);
2823 MUI_DeleteCustomClass(CL_TextIconListview);
2825 CloseLibrary(MUIMasterBase);
2827 return 0;