Don't call InvertPixelArray with negative width and/or height.
[tangerine.git] / workbench / libs / muimaster / classes / iconlist.c
blob0ba6aa074d1c836e126bea05826eb2b8b92e181d
2 /*
3 Copyright 2002-2006, The AROS Development Team. All rights reserved.
4 $Id$
5 */
7 #include <string.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <math.h>
13 #include <dos/dos.h>
14 #include <dos/datetime.h>
16 #include <exec/memory.h>
17 #include <graphics/gfx.h>
18 #include <graphics/view.h>
19 #include <graphics/rpattr.h>
20 #include <workbench/icon.h>
21 #include <workbench/workbench.h>
22 #include <devices/rawkeycodes.h>
23 #include <clib/alib_protos.h>
24 #include <proto/exec.h>
25 #include <proto/graphics.h>
26 #include <proto/utility.h>
27 #include <proto/dos.h>
28 #include <proto/intuition.h>
29 #include <proto/icon.h>
30 #include <proto/layers.h>
31 #include <proto/muimaster.h>
32 #include <proto/dos.h>
33 #include <proto/iffparse.h>
34 #include <prefs/prefhdr.h>
35 #include <prefs/wanderer.h>
36 #include <proto/cybergraphics.h>
38 #define DEBUG 0
39 #include <aros/debug.h>
41 #define MYDEBUG
42 #include "debug.h"
43 #include "mui.h"
44 #include "muimaster_intern.h"
45 #include "support.h"
46 #include "imspec.h"
47 #include "iconlist.h"
48 #include "../../../system/Wanderer/wandererprefs.h"
49 #include "../../../system/Wanderer/wanderer.h"
51 extern struct Library *MUIMasterBase;
53 #ifndef NO_ICON_POSITION
54 #define NO_ICON_POSITION (0x8000000) /* belongs to workbench/workbench.h */
55 #endif
57 #ifdef __AROS__
58 #define dol_Name dol_OldName /* This doesn't work really */
59 #endif
61 #define UPDATE_SINGLEICON 1
62 #define UPDATE_SCROLL 2
63 #define UPDATE_SORT 3
64 #define UPDATE_RESCALE 4
66 #define LEFT_BUTTON 1
67 #define RIGHT_BUTTON 2
68 #define MIDDLE_BUTTON 4
70 #define ICONLIST_TEXTMARGIN 5
72 #define ICON_LISTMODE_GRID 0
73 #define ICON_LISTMODE_ROUGH 1
75 #define ICON_TEXTMODE_OUTLINE 0
76 #define ICON_TEXTMODE_PLAIN 1
77 #define ICON_TEXTMODE_DROPSHADOW 2
79 #define ICON_TEXTMAXLEN_DEFAULT 15
80 #define ICONLIST_DRAWMODE_NORMAL 1
81 #define ICONLIST_DRAWMODE_FAST 2
83 struct IconEntry
85 struct MinNode node;
86 struct IconList_Entry entry;
88 struct DiskObject *dob; /* The icons disk objects */
90 struct FileInfoBlock fib;
91 UBYTE datebuf[LEN_DATSTRING];
92 UBYTE timebuf[LEN_DATSTRING];
93 UBYTE sizebuf[30];
94 UBYTE protbuf[8];
96 int x,y;
97 int width,height;
98 int realWidth,realHeight; /* <- includes textwidth and everything */
99 int selected;
102 struct MUI_IconData
104 APTR pool; /* Pool to allocate data from */
106 struct MinList icon_list; /* IconEntry */
107 int view_x,view_y; /* the leftmost/upper coordinates of the view */
108 int view_width,view_height; /* dimensions of the view (_mwidth(obj) and _mheight(obj)) */
109 int width,height; /* The whole width/height */
110 int mouse_pressed;
112 struct TextFont *IconFont;
114 struct MUI_EventHandlerNode ehn;
116 LONG touch_x;
117 LONG touch_y;
119 LONG click_x;
120 LONG click_y;
122 struct IconEntry *first_selected; /* the icon which has been selected first or NULL */
124 /* DoubleClick stuff */
125 ULONG last_secs;
126 ULONG last_mics;
127 struct IconEntry *last_selected;
129 /* Notify stuff */
130 struct IconList_Drop drop_entry; /* the icon where the icons have been dropped */
131 struct IconList_Click icon_click;
133 /* Internal Sorting related stuff */
135 ULONG sort_bits;
136 ULONG max_x;
137 ULONG max_y;
139 /* How to show the iconlist */
140 UBYTE wpd_IconListMode;
141 UBYTE wpd_IconTextMode;
142 ULONG wpd_IconTextMaxLen;
144 /* lasso data */
145 BOOL lasso_active;
146 struct Rectangle lasso_rect;
148 /* Render stuff */
150 /* values for update */
151 /* UPDATE_SINGLEICON = draw the given single icon only */
152 /* UPDATE_SCROLL = scroll the view by update_scrolldx/update_scrolldy */
153 /* UPDATE_RESCALE = rescaling window and update only new parts */
155 ULONG update;
156 WORD update_scrolldx;
157 WORD update_scrolldy;
158 WORD update_oldwidth;
159 WORD update_oldheight;
161 struct IconEntry *update_icon;
162 struct Rectangle *update_rect1;
163 struct Rectangle *update_rect2;
164 struct Rectangle view_rect;
166 ULONG textWidth; /* Whole textwidth for icon in pixels */
168 BOOL buffered;
171 /**************************************************************************
173 **************************************************************************/
174 int RectAndRect(struct Rectangle *a, struct Rectangle *b)
176 if ((a->MinX > b->MaxX) || (a->MinY > b->MaxY) || (a->MaxX < b->MinX) || (a->MaxY < b->MinY))
177 return 0;
178 return 1;
181 /**************************************************************************
182 get positive lasso coords
183 **************************************************************************/
184 static void GetAbsoluteLassoRect(struct MUI_IconData *data, struct Rectangle *lasso_rect)
186 WORD minx = data->lasso_rect.MinX;
187 WORD miny = data->lasso_rect.MinY;
188 WORD maxx = data->lasso_rect.MaxX;
189 WORD maxy = data->lasso_rect.MaxY;
191 if (minx > maxx)
193 /* Swap minx, maxx */
194 minx ^= maxx;
195 maxx ^= minx;
196 minx ^= maxx;
199 if (miny > maxy)
201 /* Swap miny, maxy */
202 miny ^= maxy;
203 maxy ^= miny;
204 miny ^= maxy;
207 lasso_rect->MinX = data->view_rect.MinX - data->view_x + minx;
208 lasso_rect->MinY = data->view_rect.MinY - data->view_y + miny;
209 lasso_rect->MaxX = data->view_rect.MinX - data->view_x + maxx;
210 lasso_rect->MaxY = data->view_rect.MinY - data->view_y + maxy;
213 static void InvertPixelRect(struct RastPort *rp, WORD minx, WORD miny, WORD maxx, WORD maxy)
215 if (maxx < minx)
217 /* Swap minx, maxx */
218 minx ^= maxx;
219 maxx ^= minx;
220 minx ^= maxx;
223 if (maxy < miny)
225 /* Swap miny, maxy */
226 miny ^= maxy;
227 maxy ^= miny;
228 miny ^= maxy;
231 InvertPixelArray(rp, minx, miny, maxx - minx + 1, maxy - miny + 1);
234 /**************************************************************************
235 Simple lasso drawing by inverting area outlines
236 **************************************************************************/
237 void InvertLassoOutlines(Object *obj, struct Rectangle *rect)
239 struct Rectangle lasso;
241 /* get abolute iconlist coords */
242 lasso.MinX = rect->MinX + _mleft(obj);
243 lasso.MaxX = rect->MaxX + _mleft(obj);
244 lasso.MinY = rect->MinY + _mtop(obj);
245 lasso.MaxY = rect->MaxY + _mtop(obj);
247 /* check for vertical borders */
248 if ( lasso.MinX < _mleft(obj) ) lasso.MinX += _mleft(obj) - lasso.MinX;
249 if ( lasso.MaxX > _mright(obj) ) lasso.MaxX -= lasso.MaxX - _mright(obj) - 2;
251 /* horizontal lasso lines */
252 if ( lasso.MinY > _mtop(obj) ) InvertPixelRect( _rp(obj), lasso.MinX, lasso.MinY, lasso.MaxX-1, lasso.MinY + 1);
253 else lasso.MinY += _mtop(obj) - lasso.MinY;
254 if ( lasso.MaxY < _mbottom(obj) ) InvertPixelRect( _rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX-1, lasso.MaxY + 1);
255 else lasso.MaxY -= lasso.MaxY - _mbottom(obj) - 2;
257 /* vertical lasso lines */
258 if ( lasso.MinX > _mleft(obj) ) InvertPixelRect( _rp(obj), lasso.MinX, lasso.MinY, lasso.MinX + 1, lasso.MaxY-1 );
259 if ( lasso.MaxX < _mright(obj) ) InvertPixelRect( _rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX + 1, lasso.MaxY-1 );
263 /**************************************************************************
264 As we don't use the label drawing of icon.library we also have to do
265 this by hand
266 **************************************************************************/
267 static void IconList_GetIconRectangle(Object *obj, struct MUI_IconData *data, struct IconEntry *icon, struct Rectangle *rect)
270 Get basic width/height
272 GetIconRectangleA(NULL,icon->dob,NULL,rect,NULL);
273 icon->realWidth = rect->MaxX - rect->MinX + 1;
274 icon->realHeight = rect->MaxY - rect->MinY + 1;
277 Get icon box width including text width
279 if (icon->entry.label)
281 SetFont(_rp(obj), data->IconFont);
283 ULONG textlength = strlen(icon->entry.label);
284 if ( !data->wpd_IconTextMaxLen ) data->wpd_IconTextMaxLen = ICON_TEXTMAXLEN_DEFAULT;
285 if ( textlength > data->wpd_IconTextMaxLen ) textlength = data->wpd_IconTextMaxLen;
287 LONG txwidth = TextLength(_rp(obj), icon->entry.label, textlength) + 3;
289 if ( txwidth > icon->realWidth ) icon->realWidth = txwidth;
291 icon->realHeight += data->IconFont->tf_YSize + ICONLIST_TEXTMARGIN;
295 Date/size sorting has the date/size appended under the icon label
296 only list regular files like this (drawers have no size/date output)
299 icon->entry.type != WBDRAWER &&
300 ((data->sort_bits & ICONLIST_SORT_BY_SIZE) || (data->sort_bits & ICONLIST_SORT_BY_DATE))
303 icon->realHeight += data->IconFont->tf_YSize + ( ICONLIST_TEXTMARGIN * 2 );
307 Store
309 icon->width = rect->MaxX - rect->MinX + 1;
310 icon->height = rect->MaxY - rect->MinY + 1;
311 rect->MaxX = rect->MinX + icon->realWidth - 1;
312 rect->MaxY = rect->MinY + icon->realHeight - 1;
315 /**************************************************************************
316 Draw the icon at its position
317 **************************************************************************/
319 #define DRAWICON_TESTDRAW TRUE
320 #define DRAWICON_DODRAW FALSE
322 static BOOL IconList_DrawIcon(Object *obj, struct MUI_IconData *data, struct IconEntry *icon,
323 struct RastPort *rp, BOOL onlytest)
325 struct Rectangle iconrect;
326 struct Rectangle objrect;
328 LONG tx,ty,offsetx,offsety;
329 LONG txwidth; // txheight;
331 STRPTR buf = NULL;
333 /* Get the dimensions and affected area of icon */
334 IconList_GetIconRectangle(obj, data, icon, &iconrect);
336 /* Add the relative position offset of the icon */
337 offsetx = _mleft(obj) - data->view_x + icon->x;
338 offsety = _mtop(obj) - data->view_y + icon->y;
340 iconrect.MinX += offsetx;
341 iconrect.MinY += offsety;
342 iconrect.MaxX += offsetx;
343 iconrect.MaxY += offsety;
345 /* Add the relative position of the window */
346 objrect.MinX = _mleft(obj);
347 objrect.MinY = _mtop(obj);
348 objrect.MaxX = _mright(obj);
349 objrect.MaxY = _mbottom(obj);
351 if (!RectAndRect(&iconrect, &objrect)) return FALSE;
353 /* data->update_rect1 and data->update_rect2 may
354 point to rectangles to indicate that only icons
355 in any of this rectangles need to be drawn */
357 if (data->update_rect1 && data->update_rect2)
359 if (!RectAndRect(&iconrect, data->update_rect1) &&
360 !RectAndRect(&iconrect, data->update_rect2)) return FALSE;
362 else if (data->update_rect1)
364 if (!RectAndRect(&iconrect, data->update_rect1)) return FALSE;
366 else if (data->update_rect2)
368 if (!RectAndRect(&iconrect, data->update_rect2)) return FALSE;
371 if (onlytest) return TRUE;
373 if (rp == NULL)
375 rp = _rp(obj);
377 else
379 iconrect.MinX -= offsetx;
380 iconrect.MinY -= offsety;
381 iconrect.MaxX -= offsetx;
382 iconrect.MaxY -= offsety;
385 SetABPenDrMd(rp,_pens(obj)[MPEN_TEXT],0,JAM1);
387 // Center icon
388 ULONG iconX = iconrect.MinX + ((icon->realWidth - icon->width )/2);
389 ULONG iconY = iconrect.MinY;
391 #ifndef __AROS__
392 DrawIconState
394 rp ? rp : rp, icon->dob, NULL,
395 iconX, iconY,
396 icon->selected ? IDS_SELECTED : IDS_NORMAL,
397 ICONDRAWA_EraseBackground, FALSE,
398 TAG_DONE
400 #else
401 DrawIconStateA
403 rp ? rp : rp, icon->dob, NULL,
404 iconX,
405 iconY,
406 icon->selected ? IDS_SELECTED : IDS_NORMAL,
407 TAG_DONE
409 #endif
411 if (icon->entry.label) buf = AllocVec ( 255, MEMF_CLEAR );
413 if (icon->entry.label && buf)
415 ULONG nameLength = strlen(icon->entry.label);
417 SetFont(rp, data->IconFont);
419 if ( nameLength > data->wpd_IconTextMaxLen )
420 txwidth = TextLength(rp, icon->entry.label, data->wpd_IconTextMaxLen);
421 else txwidth = TextLength(rp, icon->entry.label, nameLength);
423 memset( buf, 0 , sizeof( buf ) );
425 ULONG len = data->wpd_IconTextMaxLen;
426 // Make sure the maxlen is at least the length of ".."
427 if ( len < 2 ) len = 2;
429 if(nameLength > len)
431 strncpy(buf, icon->entry.label, len - 2);
432 strcat(buf , "..");
433 nameLength = len;
435 else
437 strncpy( buf, icon->entry.label, nameLength );
440 tx = iconrect.MinX + ((iconrect.MaxX - iconrect.MinX + 1 - txwidth)/2);
441 ty = iconY + icon->height + data->IconFont->tf_Baseline;
443 switch ( data->wpd_IconTextMode )
445 case ICON_TEXTMODE_DROPSHADOW:
446 case ICON_TEXTMODE_PLAIN:
447 SetAPen(rp, _pens(obj)[MPEN_SHADOW]);
448 Move(rp, tx, ty);
449 Text(rp, buf, nameLength);
450 break;
452 default:
453 // Outline mode:
455 SetSoftStyle(rp, FSF_BOLD, FSF_BOLD);
456 SetAPen(rp, _pens(obj)[MPEN_SHADOW]);
458 Move(rp, tx + 1, ty ); Text(rp, buf, nameLength);
459 Move(rp, tx - 1, ty ); Text(rp, buf, nameLength);
460 Move(rp, tx, ty + 1); Text(rp, buf, nameLength);
461 Move(rp, tx, ty - 1); Text(rp, buf, nameLength);
463 SetAPen(rp, _pens(obj)[MPEN_SHINE]);
464 Move(rp, tx, ty);
465 Text(rp, buf, nameLength);
466 SetSoftStyle(rp, FS_NORMAL, AskSoftStyle(rp));
467 break;
470 /*date/size sorting has the date/size appended under the icon label*/
472 if( icon->entry.type != WBDRAWER && ((data->sort_bits & ICONLIST_SORT_BY_SIZE) || (data->sort_bits & ICONLIST_SORT_BY_DATE)) )
474 if( (data->sort_bits & ICONLIST_SORT_BY_SIZE) && !(data->sort_bits & ICONLIST_SORT_BY_DATE) )
476 int i = icon->fib.fib_Size;
478 /*show byte size for small files*/
479 if( i > 9999 )
480 sprintf( buf , "%ld KB" , (LONG)(i/1024) );
481 else
482 sprintf( buf , "%ld B" , (LONG)i );
484 else
486 if( !(data->sort_bits & ICONLIST_SORT_BY_SIZE) && (data->sort_bits & ICONLIST_SORT_BY_DATE) )
488 struct DateStamp now;
489 DateStamp(&now);
491 /*if modified today show time, otherwise just show date*/
492 if( now.ds_Days == icon->fib.fib_Date.ds_Days )
493 sprintf( buf , "%s" ,icon->timebuf );
494 else
495 sprintf( buf , "%s" ,icon->datebuf );
499 nameLength = strlen(buf);
501 ULONG textwidth = TextLength(rp, buf, nameLength);
502 tx = iconrect.MinX + ((iconrect.MaxX - iconrect.MinX + 1 - textwidth)/2);
503 ty = iconY + icon->height + data->IconFont->tf_YSize + ICONLIST_TEXTMARGIN + data->IconFont->tf_Baseline;
505 switch ( data->wpd_IconTextMode )
507 case ICON_TEXTMODE_DROPSHADOW:
508 case ICON_TEXTMODE_PLAIN:
509 SetAPen(rp, _pens(obj)[MPEN_SHADOW]);
510 Move(rp, tx, ty); Text(rp, buf, nameLength);
511 break;
513 default:
514 // Outline mode..
515 SetSoftStyle(rp, FSF_BOLD, FSF_BOLD);
516 SetAPen(rp, _pens(obj)[MPEN_SHADOW]);
518 Move(rp, tx + 1, ty ); Text(rp, buf, nameLength);
519 Move(rp, tx - 1, ty ); Text(rp, buf, nameLength);
520 Move(rp, tx, ty + 1); Text(rp, buf, nameLength);
521 Move(rp, tx, ty - 1); Text(rp, buf, nameLength);
523 SetAPen(rp, _pens(obj)[MPEN_SHINE]);
524 Move(rp, tx, ty);
525 Text(rp, buf, nameLength);
526 SetSoftStyle(rp, FS_NORMAL, AskSoftStyle(rp));
527 break;
531 // Free up icontext memory
533 FreeVec ( buf );
535 return TRUE;
538 /**************************************************************************
540 **************************************************************************/
541 static void IconList_RethinkDimensions(Object *obj, struct MUI_IconData *data, struct IconEntry *singleicon)
543 struct IconEntry *icon;
544 WORD maxx = data->width - 1, maxy = data->height - 1;
546 if (!(_flags(obj)&MADF_SETUP)) return;
548 icon = singleicon ? singleicon : List_First(&data->icon_list);
550 while (icon)
552 if (icon->dob && icon->x != NO_ICON_POSITION && icon->y != NO_ICON_POSITION)
554 struct Rectangle icon_rect;
556 IconList_GetIconRectangle(obj, data, icon, &icon_rect);
558 icon_rect.MinX += icon->x;
559 icon_rect.MaxX += icon->x;
560 icon_rect.MinY += icon->y;
561 icon_rect.MaxY += icon->y;
563 if (icon_rect.MaxX > maxx) maxx = icon_rect.MaxX;
564 if (icon_rect.MaxY > maxy) maxy = icon_rect.MaxY;
568 if (singleicon) break;
570 icon = Node_Next(icon);
573 /* update our view when max x/y have changed */
574 if (maxx + 1 != data->width)
576 data->width = maxx + 1;
577 set(obj, MUIA_IconList_Width, data->width);
579 if (maxy + 1 != data->height)
581 data->height = maxy + 1;
582 set(obj, MUIA_IconList_Height, data->height);
587 /**************************************************************************
588 Checks weather we can place a icon with the given dimesions at the
589 suggested positions.
591 atx and aty are absolute positions
592 **************************************************************************/
594 static int IconList_CouldPlaceIcon(Object *obj, struct MUI_IconData *data, struct IconEntry *toplace, int atx, int aty)
596 struct IconEntry *icon;
597 struct Rectangle toplace_rect;
599 IconList_GetIconRectangle(obj, toplace, &toplace_rect);
600 toplace_rect.MinX += atx;
601 toplace_rect.MaxX += atx;
602 toplace_rect.MinY += aty;
603 toplace_rect.MaxY += aty;
605 icon = List_First(&data->icon_list);
606 while (icon)
608 if (icon->dob && icon->x != NO_ICON_POSITION && icon->y != NO_ICON_POSITION)
610 struct Rectangle icon_rect;
611 IconList_GetIconRectangle(obj, icon, &icon_rect);
612 icon_rect.MinX += icon->x;
613 icon_rect.MaxX += icon->x;
614 icon_rect.MinY += icon->y;
615 icon_rect.MaxY += icon->y;
617 if (RectAndRect(&icon_rect, &toplace_rect))
618 return FALSE; *//* There is already an icon on this place *//*
620 icon = Node_Next(icon);
622 return 1;
626 /**************************************************************************
627 Place the icon at atx and aty.
629 atx and aty are absolute positions
630 **************************************************************************/
632 static void IconList_PlaceIcon(Object *obj, struct MUI_IconData *data, struct IconEntry *toplace, int atx, int aty)
634 #if 0
635 struct Rectangle toplace_rect;
637 IconList_GetIconRectangle(obj, toplace, &toplace_rect);
638 toplace_rect.MinX += atx + data->view_x;
639 toplace_rect.MaxX += atx + data->view_x;
640 toplace_rect.MinY += aty + data->view_y;
641 toplace_rect.MaxY += aty + data->view_y;
642 #endif
643 toplace->x = atx;
644 toplace->y = aty;
645 #if 0
646 *//* update our view *//*
647 if (toplace_rect.MaxX - data->view_x > data->width)
649 data->width = toplace_rect.MaxX - data->view_x;
650 set(obj, MUIA_IconList_Width, data->width);
653 if (toplace_rect.MaxY - data->view_y > data->height)
655 data->height = toplace_rect.MaxY - data->view_y;
656 set(obj, MUIA_IconList_Height, data->height);
658 #endif
661 /**************************************************************************
662 MUIM_PositionIcons - Place icons with NO_ICON_POSITION coords somewhere
663 **************************************************************************/
665 IPTR IconList__MUIM_PositionIcons(struct IClass *cl, Object *obj, struct MUIP_IconList_PositionIcons *msg)
667 struct MUI_IconData *data = INST_DATA(cl, obj);
668 struct IconEntry *icon;
670 int spacing = 4;
671 int top = spacing;
672 int left = spacing;
673 int gridx = 32;
674 int gridy = 32;
675 int cur_x = spacing;
676 int cur_y = spacing;
677 int maxw = 0; // There two are the max icon width recorded in a column
678 int maxh = 0; // or the max icon height recorded in a row depending
679 int listMode = (int)data->wpd_IconListMode;
681 BOOL next = TRUE;
682 int maxWidth = 0, maxHeight = 0;
683 icon = List_First(&data->icon_list);
685 // If going by grid, first traverse and find the highest w/h
686 if ( listMode == ICON_LISTMODE_GRID )
688 while (icon != NULL)
690 struct Rectangle iconrect;
691 IconList_GetIconRectangle(obj, data, icon, &iconrect);
692 if ( icon->realWidth > maxWidth )
693 maxWidth = icon->realWidth;
694 if ( icon->realHeight > maxHeight )
695 maxHeight = icon->realHeight;
696 icon = Node_Next(icon);
700 // Now go to the actual positioning
701 icon = List_First(&data->icon_list);
702 while (icon != NULL)
704 if (icon->dob != NULL)
706 icon->x = cur_x;
707 icon->y = cur_y;
709 if ( listMode == ICON_LISTMODE_GRID )
711 gridx = maxWidth + spacing;
712 gridy = maxHeight + spacing;
713 // center icons on grid
714 icon->x += ( maxWidth - icon->realWidth ) / 2;
715 icon->y += ( maxHeight - icon->realHeight ) / 2;
717 else
719 // Update the realWidth/realHeight values every time we position an icon!
720 struct Rectangle iconrect;
721 IconList_GetIconRectangle(obj, data, icon, &iconrect);
722 gridx = icon->realWidth + spacing;
723 gridy = icon->realHeight + spacing;
726 if( data->sort_bits & ICONLIST_DISP_VERTICAL )
728 if ( maxw < gridx ) maxw = gridx;
729 cur_y += gridy;
731 if (cur_y >= data->view_height )
733 next = FALSE;
734 cur_x += maxw;
735 cur_y = top;
738 else
740 if ( maxh < gridy ) maxh = gridy;
741 cur_x += gridx;
743 if (cur_x >= data->view_width )
745 next = FALSE;
746 cur_x = left;
747 cur_y += maxh;
751 if ( next )
752 icon = Node_Next(icon);
753 next = TRUE;
755 IconList_RethinkDimensions(obj, data, NULL);
756 return 0;
759 /*static void IconList_FixNoPositionIcons(Object *obj, struct MUI_IconData *data)
761 struct IconEntry *icon;
762 int cur_x = data->view_x + 36;
763 int cur_y = data->view_y + 4;
765 icon = List_First(&data->icon_list);
766 while (icon)
768 if (icon->dob && icon->x == NO_ICON_POSITION && icon->y == NO_ICON_POSITION)
770 int loops = 0;
771 int cur_x_save = cur_x;
772 int cur_y_save = cur_y;
773 struct Rectangle icon_rect;
775 IconList_GetIconRectangle(obj, icon, &icon_rect);
776 icon_rect.MinX += cur_x - icon->width/2 + data->view_x;
777 if (icon_rect.MinX < 0)
778 cur_x -= icon_rect.MinX;
780 while (!IconList_CouldPlaceIcon(obj, data, icon, cur_x - icon->width/2, cur_y) && loops < 5000)
782 cur_y++;
784 if (cur_y + icon->height > data->view_x + data->view_height) *//* on both sides -1 *//*
786 cur_x += 72;
787 cur_y = data->view_y + 4;
791 IconList_PlaceIcon(obj, data, icon, cur_x - icon->width/2, cur_y);
793 if (icon_rect.MinX < 0)
795 cur_x = cur_x_save;
796 cur_y = cur_y_save;
799 icon = Node_Next(icon);
802 IconList_RethinkDimensions(obj, data, NULL);
805 /**************************************************************************
806 OM_NEW
807 **************************************************************************/
808 IPTR IconList__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
810 struct MUI_IconData *data;
811 //struct TagItem *tag, *tags;
812 struct TextFont *WindowFont = NULL;
814 WindowFont = (struct TextFont *) GetTagData(MUIA_Font, (IPTR) NULL, msg->ops_AttrList);
816 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
817 MUIA_Dropable, TRUE,
818 MUIA_Font, MUIV_Font_Tiny,
819 TAG_MORE, (IPTR) msg->ops_AttrList);
820 if (!obj) return FALSE;
822 data = INST_DATA(cl, obj);
823 data->last_selected = NULL;
825 // Get some initial values
826 data->wpd_IconListMode = GetTagData(MUIA_IconList_ListMode, 0, msg->ops_AttrList);
827 data->wpd_IconTextMode = GetTagData(MUIA_IconList_TextMode, 0, msg->ops_AttrList);
828 data->wpd_IconTextMaxLen = GetTagData(MUIA_IconList_TextMaxLen, 0, msg->ops_AttrList);
829 if ( data->wpd_IconTextMaxLen <= 0 )
830 data->wpd_IconTextMaxLen = ICON_TEXTMAXLEN_DEFAULT;
832 data->buffered = (BOOL) GetTagData(MUIA_IconList_DoubleBuffered, 0, msg->ops_AttrList);
834 NewList((struct List*)&data->icon_list);
836 set(obj,MUIA_FillArea,FALSE);
838 if (WindowFont == NULL) data->IconFont = _font(obj);
839 else data->IconFont = WindowFont;
841 D(bug("[iconlist] Used Font = %x\n", data->IconFont));
843 data->pool = CreatePool(0,4096,4096);
844 if (!data->pool)
846 CoerceMethod(cl,obj,OM_DISPOSE);
847 return (IPTR)NULL;
850 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY;
851 data->ehn.ehn_Priority = 0;
852 data->ehn.ehn_Flags = 0;
853 data->ehn.ehn_Object = obj;
854 data->ehn.ehn_Class = cl;
856 data->sort_bits = 0;
858 return (IPTR)obj;
861 /**************************************************************************
862 OM_DISPOSE
863 **************************************************************************/
864 IPTR IconList__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
866 struct MUI_IconData *data = INST_DATA(cl, obj);
867 struct IconEntry *node;
869 node = List_First(&data->icon_list);
870 while (node)
872 if (node->dob) FreeDiskObject(node->dob);
873 node = Node_Next(node);
876 if (data->pool) DeletePool(data->pool);
878 DoSuperMethodA(cl,obj,msg);
879 return 0;
883 /**************************************************************************
884 OM_SET
885 **************************************************************************/
886 IPTR IconList__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
888 struct MUI_IconData *data = INST_DATA(cl, obj);
889 struct TagItem *tag, *tags;
890 WORD oldleft = data->view_x, oldtop = data->view_y;
891 WORD oldwidth = data->view_width, oldheight = data->view_height;
893 /* parse initial taglist */
894 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
896 switch (tag->ti_Tag)
898 case MUIA_Font:
899 data->IconFont = (struct TextFont*)tag->ti_Data;
900 break;
902 case MUIA_IconList_Left:
903 if (data->view_x != tag->ti_Data)
904 data->view_x = tag->ti_Data;
905 break;
907 case MUIA_IconList_ListMode:
908 data->wpd_IconListMode = tag->ti_Data;
909 break;
911 case MUIA_IconList_TextMode:
912 data->wpd_IconTextMode = tag->ti_Data;
913 break;
915 case MUIA_IconList_TextMaxLen:
916 data->wpd_IconTextMaxLen = tag->ti_Data;
917 break;
919 case MUIA_IconList_Top:
920 if (data->view_y != tag->ti_Data)
921 data->view_y = tag->ti_Data;
922 break;
926 if ((oldleft != data->view_x) || (oldtop != data->view_y))
928 data->update = UPDATE_SCROLL;
929 data->update_scrolldx = data->view_x - oldleft;
930 data->update_scrolldy = data->view_y - oldtop;
931 MUI_Redraw(obj, MADF_DRAWUPDATE);
934 return DoSuperMethodA(cl, obj, (Msg)msg);
937 /**************************************************************************
938 OM_GET
939 **************************************************************************/
940 IPTR IconList__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
942 /* small macro to simplify return value storage */
943 #define STORE *(msg->opg_Storage)
944 struct MUI_IconData *data = INST_DATA(cl, obj);
946 switch (msg->opg_AttrID)
948 case MUIA_IconList_Left: STORE = data->view_x; return 1;
949 case MUIA_IconList_Top: STORE = data->view_y; return 1;
950 case MUIA_IconList_Width: STORE = data->width; return 1;
951 case MUIA_IconList_Height: STORE = data->height; return 1;
952 case MUIA_IconList_IconsDropped: STORE = (IPTR)&data->drop_entry; return 1;
953 case MUIA_IconList_Clicked: STORE = (ULONG)&data->icon_click; return 1;
954 case MUIA_IconList_ListMode: STORE = (ULONG)&data->wpd_IconListMode; return 1;
955 case MUIA_IconList_TextMode: STORE = (ULONG)&data->wpd_IconTextMode; return 1;
956 case MUIA_IconList_TextMaxLen: STORE = (ULONG)&data->wpd_IconTextMaxLen; return 1;
959 if (DoSuperMethodA(cl, obj, (Msg) msg))
960 return 1;
961 return 0;
962 #undef STORE
965 /**************************************************************************
966 MUIM_Setup
967 **************************************************************************/
968 IPTR IconList__MUIM_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
970 struct MUI_IconData *data = INST_DATA(cl, obj);
971 struct IconEntry *node;
973 if (!DoSuperMethodA(cl, obj, (Msg) msg)) return 0;
975 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
977 Object *prefs = (Object *) XGET(_app(obj), MUIA_Wanderer_Prefs);
978 data->wpd_IconListMode = XGET(prefs, MUIA_WandererPrefs_Icon_ListMode);
979 data->wpd_IconTextMode = XGET(prefs, MUIA_WandererPrefs_Icon_TextMode);
980 data->wpd_IconTextMaxLen = XGET(prefs, MUIA_WandererPrefs_Icon_TextMaxLen);
982 node = List_First(&data->icon_list);
983 while (node)
985 if (!node->dob)
987 node->dob = GetIconTags
989 node->entry.filename,
990 ICONGETA_FailIfUnavailable, FALSE,
991 ICONGETA_Label, (IPTR) node->entry.label,
992 TAG_DONE
995 node = Node_Next(node);
997 return 1;
1000 /**************************************************************************
1001 MUIM_Show
1002 **************************************************************************/
1003 IPTR IconList__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
1005 struct MUI_IconData *data = INST_DATA(cl, obj);
1006 WORD newleft, newtop;
1007 IPTR rc;
1009 rc = DoSuperMethodA(cl, obj, (Msg)msg);
1011 newleft = data->view_x;
1012 newtop = data->view_y;
1014 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
1015 if (newleft < 0) newleft = 0;
1017 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
1018 if (newtop < 0) newtop = 0;
1020 if ((newleft != data->view_x) || (newtop != data->view_y))
1022 SetAttrs(obj, MUIA_IconList_Left, newleft,
1023 MUIA_IconList_Top, newtop,
1024 TAG_DONE);
1027 SetFont(_rp(obj), data->IconFont);
1028 return rc;
1032 /**************************************************************************
1033 MUIM_Cleanup
1034 **************************************************************************/
1035 IPTR IconList__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
1037 struct MUI_IconData *data = INST_DATA(cl, obj);
1039 struct IconEntry *node;
1041 node = List_First(&data->icon_list);
1042 while (node)
1044 if (node->dob)
1046 FreeDiskObject(node->dob);
1047 node->dob = NULL;
1049 node = Node_Next(node);
1052 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1053 return DoSuperMethodA(cl, obj, (Msg) msg);
1056 /**************************************************************************
1057 MUIM_AskMinMax
1058 **************************************************************************/
1059 IPTR IconList__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
1061 ULONG rc = DoSuperMethodA(cl, obj, (Msg) msg);
1063 msg->MinMaxInfo->MinWidth += 96;
1064 msg->MinMaxInfo->MinHeight += 64;
1066 msg->MinMaxInfo->DefWidth += 200;
1067 msg->MinMaxInfo->DefHeight += 180;
1069 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
1070 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
1072 return rc;
1075 /**************************************************************************
1076 MUIM_Layout
1077 **************************************************************************/
1078 IPTR IconList__MUIM_Layout(struct IClass *cl, Object *obj,struct MUIP_Layout *msg)
1080 struct MUI_IconData *data = INST_DATA(cl, obj);
1081 ULONG rc = DoSuperMethodA(cl,obj,(Msg)msg);
1082 data->view_width = _mwidth(obj);
1083 data->view_height = _mheight(obj);
1084 return rc;
1087 /**************************************************************************
1088 MUIM_Draw - draw the IconList
1089 **************************************************************************/
1090 IPTR IconList__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
1092 struct MUI_IconData *data = INST_DATA(cl, obj);
1093 APTR clip;
1094 struct IconEntry *icon;
1095 BOOL buffereddraw = FALSE;
1096 BOOL updateall = FALSE;
1097 ULONG update_oldwidth = 0, update_oldheight = 0;
1098 DoSuperMethodA(cl, obj, (Msg) msg);
1100 // If window size changes, only update needed areas
1101 if (data->update_oldwidth == 0) data->update_oldwidth = data->view_width;
1102 if (data->update_oldheight == 0) data->update_oldheight = data->view_height;
1103 if (data->update_oldwidth != data->view_width || data->update_oldheight != data->view_height)
1105 if ( data->update != UPDATE_SCROLL )
1107 data->update = UPDATE_RESCALE;
1108 update_oldwidth = data->update_oldwidth;
1109 update_oldheight = data->update_oldheight;
1110 data->update_oldwidth = data->view_width;
1111 data->update_oldheight = data->view_height;
1115 if (msg->flags & MADF_DRAWUPDATE || data->update == UPDATE_RESCALE)
1117 if (data->update == UPDATE_SINGLEICON) /* draw only a single icon at update_icon */
1119 struct Rectangle rect;
1121 IconList_GetIconRectangle(obj, data, data->update_icon, &rect);
1123 rect.MinX += _mleft(obj) - data->view_x + data->update_icon->x;
1124 rect.MaxX += _mleft(obj) - data->view_x + data->update_icon->x;
1125 rect.MinY += _mtop(obj) - data->view_y + data->update_icon->y;
1126 rect.MaxY += _mtop(obj) - data->view_y + data->update_icon->y;
1128 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
1130 #if 1
1131 DoMethod(
1132 obj, MUIM_DrawBackground,
1133 rect.MinX, rect.MinY,
1134 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
1135 data->view_x + (rect.MinX - _mleft(obj)), data->view_y + (rect.MinY - _mtop(obj)),
1138 #else
1139 DoMethod(obj, MUIM_DrawBackground, _mleft(obj), _mtop(obj),
1140 _mwidth(obj), _mheight(obj),
1141 data->view_x, data->view_y, 0);
1142 #endif
1144 /* We could have deleted also other icons so they must be redrawn */
1145 icon = List_First(&data->icon_list);
1146 while (icon)
1148 if (icon != data->update_icon)
1150 struct Rectangle rect2;
1151 IconList_GetIconRectangle(obj, data, icon, &rect2);
1153 rect2.MinX += _mleft(obj) - data->view_x + icon->x;
1154 rect2.MaxX += _mleft(obj) - data->view_x + icon->x;
1155 rect2.MinY += _mtop(obj) - data->view_y + icon->y;
1156 rect2.MaxY += _mtop(obj) - data->view_y + icon->y;
1158 if (RectAndRect(&rect,&rect2))
1160 // Update icon here
1161 IconList_DrawIcon(obj, data, icon, NULL, DRAWICON_DODRAW);
1164 icon = Node_Next(icon);
1167 IconList_DrawIcon(obj, data, data->update_icon, NULL, DRAWICON_DODRAW);
1168 data->update = 0;
1169 MUI_RemoveClipping(muiRenderInfo(obj),clip);
1170 return 0;
1172 else if (data->update == UPDATE_SCROLL)
1174 struct Region *region;
1175 struct Rectangle xrect, yrect;
1176 BOOL scroll_caused_damage;
1178 //if (data->buffered)
1179 // updateall = TRUE;
1181 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
1183 data->update = 0;
1185 if (!updateall)
1188 if ((abs(data->update_scrolldx) >= _mwidth(obj)) ||
1189 (abs(data->update_scrolldy) >= _mheight(obj)))
1191 MUI_Redraw(obj, MADF_DRAWOBJECT);
1192 return 0;
1195 region = NewRegion();
1196 if (!region)
1198 MUI_Redraw(obj, MADF_DRAWOBJECT);
1199 return 0;
1202 if (data->update_scrolldx > 0)
1204 xrect.MinX = _mright(obj) - data->update_scrolldx;
1205 xrect.MinY = _mtop(obj);
1206 xrect.MaxX = _mright(obj);
1207 xrect.MaxY = _mbottom(obj);
1209 OrRectRegion(region, &xrect);
1211 data->update_rect1 = &xrect;
1213 else if (data->update_scrolldx < 0)
1215 xrect.MinX = _mleft(obj);
1216 xrect.MinY = _mtop(obj);
1217 xrect.MaxX = _mleft(obj) - data->update_scrolldx;
1218 xrect.MaxY = _mbottom(obj);
1220 OrRectRegion(region, &xrect);
1222 data->update_rect1 = &xrect;
1225 if (data->update_scrolldy > 0)
1227 yrect.MinX = _mleft(obj);
1228 yrect.MinY = _mbottom(obj) - data->update_scrolldy;
1229 yrect.MaxX = _mright(obj);
1230 yrect.MaxY = _mbottom(obj);
1232 OrRectRegion(region, &yrect);
1234 data->update_rect2 = &yrect;
1236 else if (data->update_scrolldy < 0)
1238 yrect.MinX = _mleft(obj);
1239 yrect.MinY = _mtop(obj);
1240 yrect.MaxX = _mright(obj);
1241 yrect.MaxY = _mtop(obj) - data->update_scrolldy;
1243 OrRectRegion(region, &yrect);
1245 data->update_rect2 = &yrect;
1248 ScrollRasterBF(_rp(obj),
1249 data->update_scrolldx,
1250 data->update_scrolldy,
1251 _mleft(obj),
1252 _mtop(obj),
1253 _mright(obj),
1254 _mbottom(obj));
1256 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
1258 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1260 MUI_Redraw(obj, MADF_DRAWOBJECT);
1262 data->update_rect1 = data->update_rect2 = NULL;
1264 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1266 if (scroll_caused_damage)
1268 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
1270 /* Theoretically it might happen that more damage is caused
1271 after ScrollRaster. By something else, like window movement
1272 in front of our window. Therefore refresh root object of
1273 window, not just this object */
1275 Object *o = NULL;
1277 get(_win(obj),MUIA_Window_RootObject, &o);
1278 MUI_Redraw(o, MADF_DRAWOBJECT);
1280 MUI_EndRefresh(muiRenderInfo(obj), 0);
1284 return 0;
1287 else if (data->update == UPDATE_RESCALE)
1289 struct Region *region;
1290 struct Rectangle wrect, hrect;
1291 ULONG diffw = 0, diffh = 0;
1293 if (data->buffered)
1294 updateall = TRUE;
1296 data->update = 0;
1298 if (!updateall)
1300 if (!(region = NewRegion()))
1302 MUI_Redraw(obj, MADF_DRAWOBJECT);
1303 return 0;
1306 if ( data->view_width > update_oldwidth )
1307 diffw = data->view_width - update_oldwidth;
1308 if ( data->view_height > update_oldheight )
1309 diffh = data->view_height - update_oldheight;
1311 if (diffw)
1313 wrect.MinX = _mright(obj) - diffw;
1314 wrect.MinY = _mtop(obj);
1315 wrect.MaxX = _mright(obj);
1316 wrect.MaxY = _mbottom(obj);
1317 OrRectRegion(region, &wrect);
1318 data->update_rect1 = &wrect;
1321 if (diffh)
1323 hrect.MinX = _mleft(obj);
1324 hrect.MinY = _mbottom(obj) - diffh;
1325 hrect.MaxX = _mright(obj);
1326 hrect.MaxY = _mbottom(obj);
1327 OrRectRegion(region, &hrect);
1328 data->update_rect2 = &hrect;
1331 if (diffh||diffw)
1333 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1334 MUI_Redraw(obj, MADF_DRAWOBJECT);
1335 data->update_rect1 = data->update_rect2 = NULL;
1336 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1337 } else DisposeRegion(region);
1339 return 0;
1344 else updateall = TRUE;
1346 if (updateall)
1348 struct Region *reg = NULL;
1350 if (data->buffered) reg = NewRegion();
1352 if (reg)
1354 struct Rectangle rect = {_mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj)};
1355 if (OrRectRegion(reg, &rect))
1357 BOOL ok = TRUE;
1358 icon = List_First(&data->icon_list);
1359 while (icon && ok)
1361 if (icon->dob && icon->x != NO_ICON_POSITION && icon->y != NO_ICON_POSITION)
1363 struct Rectangle iconrect;
1365 /* Get the dimensions and affected area of icon */
1366 IconList_GetIconRectangle(obj, data, icon, &iconrect);
1368 /* Add the relative position offset of the icon */
1369 iconrect.MinX += _mleft(obj) - data->view_x + icon->x;
1370 iconrect.MaxX += _mleft(obj) - data->view_x + icon->x;
1371 iconrect.MinY += _mtop(obj) - data->view_y + icon->y;
1372 iconrect.MaxY += _mtop(obj) - data->view_y + icon->y;
1374 if(ClearRectRegion(reg, &iconrect)==0) ok = FALSE;
1376 icon = Node_Next(icon);
1378 if (!ok)
1380 DisposeRegion(reg);
1381 reg = NULL;
1384 else
1386 DisposeRegion(reg);
1387 reg = NULL;
1391 if (reg)
1393 buffereddraw = TRUE;
1394 clip = MUI_AddClipRegion(muiRenderInfo(obj), reg);
1397 DoMethod(
1398 obj, MUIM_DrawBackground, _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj),
1399 data->view_x, data->view_y, 0
1402 if (reg) MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1406 /* At we see if there any Icons without proper position, this is the wrong place here,
1407 * it should be done after all icons have been loaded */
1409 /*ric - no need!: IconList_FixNoPositionIcons(obj, data);*/
1411 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
1413 icon = List_First(&data->icon_list);
1414 while (icon)
1416 if (icon->dob && icon->x != NO_ICON_POSITION && icon->y != NO_ICON_POSITION)
1418 if (buffereddraw && IconList_DrawIcon(obj, data, icon, NULL, DRAWICON_TESTDRAW))
1420 struct Rectangle ir;
1422 /* Get the dimensions and affected area of icon */
1423 IconList_GetIconRectangle(obj, data, icon, &ir);
1425 /* Add the relative position offset of the icon */
1427 ir.MinX += _mleft(obj) - data->view_x + icon->x;
1428 ir.MaxX += _mleft(obj) - data->view_x + icon->x;
1429 ir.MinY += _mtop(obj) - data->view_y + icon->y;
1430 ir.MaxY += _mtop(obj) - data->view_y + icon->y;
1432 struct RastPort *mrp = CreateRastPort();
1433 if (mrp)
1435 mrp->BitMap = AllocBitMap(ir.MaxX-ir.MinX+1, ir.MaxY-ir.MinY+1, 1, BMF_INTERLEAVED|BMF_MINPLANES, _rp(obj)->BitMap);
1436 if (mrp->BitMap)
1438 DoMethod(
1439 obj, MUIM_DrawBackgroundBuffered, mrp,
1440 ir.MinX, ir.MinY,
1441 ir.MaxX - ir.MinX + 1, ir.MaxY - ir.MinY + 1,
1442 data->view_x + (ir.MinX - _mleft(obj)), data->view_y + (ir.MinY - _mtop(obj)),
1446 else
1448 FreeRastPort(mrp);
1449 mrp = NULL;
1452 if (mrp)
1454 struct Rectangle clip;
1456 clip.MinX = 0;
1457 clip.MinY = 0;
1458 clip.MaxX = ir.MaxX-ir.MinX;
1459 clip.MaxY = ir.MaxY-ir.MinY;
1461 SetRPAttrs(mrp, RPTAG_ClipRectangle, (IPTR)&clip, RPTAG_ClipRectangleFlags, 0, TAG_DONE);
1463 IconList_DrawIcon(obj, data, icon, mrp, DRAWICON_DODRAW);
1464 BltBitMapRastPort(mrp->BitMap, 0, 0, _rp(obj), ir.MinX, ir.MinY, ir.MaxX-ir.MinX+1, ir.MaxY-ir.MinY+1, 0xc0);
1465 FreeBitMap(mrp->BitMap);
1466 FreeRastPort(mrp);
1469 else
1471 DoMethod(
1472 obj, MUIM_DrawBackground,
1473 ir.MinX, ir.MinY,
1474 ir.MaxX - ir.MinX + 1, ir.MaxY - ir.MinY + 1,
1475 data->view_x + (ir.MinX - _mleft(obj)), data->view_y + (ir.MinY - _mtop(obj)),
1478 IconList_DrawIcon(obj, data, icon, NULL, DRAWICON_DODRAW);
1480 } else IconList_DrawIcon(obj, data, icon, NULL, DRAWICON_DODRAW);
1483 icon = Node_Next(icon);
1486 MUI_RemoveClipping(muiRenderInfo(obj),clip);
1488 data->update = 0;
1490 return 0;
1493 /**************************************************************************
1494 MUIM_IconList_Refresh
1495 Implemented by subclasses
1496 **************************************************************************/
1497 IPTR IconList__MUIM_Update(struct IClass *cl, Object *obj, struct MUIP_IconList_Update *msg)
1499 return 1;
1502 /**************************************************************************
1503 MUIM_IconList_Clear
1504 **************************************************************************/
1505 IPTR IconList__MUIM_Clear(struct IClass *cl, Object *obj, struct MUIP_IconList_Clear *msg)
1507 struct MUI_IconData *data = INST_DATA(cl, obj);
1508 struct IconEntry *node;
1510 while ((node = (struct IconEntry*)RemTail((struct List*)&data->icon_list)))
1512 if (node->dob) FreeDiskObject(node->dob);
1513 if (node->entry.label) FreePooled(data->pool,node->entry.label,strlen(node->entry.label)+1);
1514 if (node->entry.filename) FreePooled(data->pool,node->entry.filename,strlen(node->entry.filename)+1);
1515 FreePooled(data->pool,node,sizeof(struct IconEntry));
1518 data->first_selected = NULL;
1519 data->view_x = data->view_y = data->width = data->height = 0;
1520 /*data->sort_bits = 0;*/
1522 data->max_x = data->max_y = 32; /*default icon size*/
1524 SetAttrs(obj, MUIA_IconList_Left, data->view_x,
1525 MUIA_IconList_Top, data->view_y,
1526 MUIA_IconList_Width, data->width,
1527 MUIA_IconList_Height, data->height,
1528 TAG_DONE);
1530 MUI_Redraw(obj,MADF_DRAWOBJECT);
1531 return 1;
1534 /**************************************************************************
1535 MUIM_IconList_Add.
1536 Returns 0 on failure otherwise 1
1537 **************************************************************************/
1538 IPTR IconList__MUIM_Add(struct IClass *cl, Object *obj, struct MUIP_IconList_Add *msg)
1540 struct MUI_IconData *data = INST_DATA(cl, obj);
1541 struct IconEntry *entry;
1542 struct DateTime dt;
1543 UBYTE *sp;
1545 struct DiskObject *dob;
1546 struct Rectangle rect;
1548 /*disk object (icon)*/
1549 dob = GetIconTags
1551 msg->filename,
1552 ICONGETA_FailIfUnavailable, FALSE,
1553 ICONGETA_Label, (IPTR) msg->label,
1554 TAG_DONE
1557 if (!dob) return 0;
1559 if (!(entry = AllocPooled(data->pool,sizeof(struct IconEntry))))
1561 FreeDiskObject(dob);
1562 return 0;
1565 memset(entry,0,sizeof(struct IconEntry));
1567 /*alloc filename*/
1568 if (!(entry->entry.filename = AllocPooled(data->pool,strlen(msg->filename)+1)))
1570 FreePooled(data->pool,entry,sizeof(struct IconEntry));
1571 FreeDiskObject(dob);
1572 return 0;
1575 /*alloc icon label*/
1576 if (!(entry->entry.label = AllocPooled(data->pool,strlen(msg->label)+1)))
1578 FreePooled(data->pool,entry->entry.filename,strlen(entry->entry.filename)+1);
1579 FreePooled(data->pool,entry,sizeof(struct IconEntry));
1580 FreeDiskObject(dob);
1581 return 0;
1584 /*file info block*/
1585 if( msg->fib )
1587 entry->fib = *msg->fib;
1589 if (entry->fib.fib_DirEntryType > 0)
1591 strcpy(entry->sizebuf, "Drawer");
1593 else
1595 sprintf(entry->sizebuf, "%ld", entry->fib.fib_Size);
1598 dt.dat_Stamp = entry->fib.fib_Date;
1599 dt.dat_Format = FORMAT_DEF;
1600 dt.dat_Flags = 0;
1601 dt.dat_StrDay = NULL;
1602 dt.dat_StrDate = entry->datebuf;
1603 dt.dat_StrTime = entry->timebuf;
1605 DateToStr(&dt);
1607 sp = entry->protbuf;
1608 *sp++ = (entry->fib.fib_Protection & FIBF_SCRIPT) ? 's' : '-';
1609 *sp++ = (entry->fib.fib_Protection & FIBF_PURE) ? 'p' : '-';
1610 *sp++ = (entry->fib.fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
1611 *sp++ = (entry->fib.fib_Protection & FIBF_READ) ? '-' : 'r';
1612 *sp++ = (entry->fib.fib_Protection & FIBF_WRITE) ? '-' : 'w';
1613 *sp++ = (entry->fib.fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
1614 *sp++ = (entry->fib.fib_Protection & FIBF_DELETE) ? '-' : 'd';
1615 *sp++ = '\0';
1617 entry->entry.type = entry->fib.fib_DirEntryType;
1620 else
1622 entry->entry.type = ST_USERDIR;
1625 strcpy(entry->entry.filename,msg->filename);
1626 strcpy(entry->entry.label,msg->label);
1628 entry->dob = dob;
1629 entry->entry.udata = NULL;
1630 entry->x = dob->do_CurrentX;
1631 entry->y = dob->do_CurrentY;
1633 /* Use a geticonrectanble routine that gets textwidth! */
1634 IconList_GetIconRectangle(obj, data, entry, &rect);
1637 entry->width = rect.MaxX - rect.MinX + 1;
1638 entry->height = rect.MaxY - rect.MinY + 1;
1640 /*D(bug("add %s %i\n" , entry->entry.label , (entry->entry.type & 255) ));*/
1642 /*hack, force grid to recognise largest icon!*/
1643 if( entry->width > data->max_x ) data->max_x = entry->width;
1644 if( entry->height > data->max_y ) data->max_y = entry->height;
1646 AddHead((struct List*)&data->icon_list,(struct Node*)entry);
1648 return 1;
1651 fib_DirEntryType,ST_USERDIR; LONG type
1654 static void DoWheelMove(struct IClass *cl, Object *obj, LONG wheelx, LONG wheely,
1655 UWORD qual)
1657 struct MUI_IconData *data = INST_DATA(cl, obj);
1659 WORD newleft = data->view_x;
1660 WORD newtop = data->view_y;
1662 /* If vertical wheel is used but there's nothing to scroll
1663 vertically (everything visible already), scroll horizontally. */
1665 if (wheely && !wheelx && data->height <= _mheight(obj))
1667 wheelx = wheely; wheely = 0;
1670 /* If vertical wheel is used and one of the ALT keys is down,
1671 scroll horizontally */
1673 if (wheely && !wheelx && (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)))
1675 wheelx = wheely; wheely = 0;
1678 if (qual & (IEQUALIFIER_CONTROL))
1680 if (wheelx < 0) newleft = 0;
1681 if (wheelx > 0) newleft = data->width;
1682 if (wheely < 0) newtop = 0;
1683 if (wheely > 0) newtop = data->height;
1685 else if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
1687 newleft += (wheelx * _mwidth(obj));
1688 newtop += (wheely * _mheight(obj));
1690 else
1692 newleft += wheelx * 30;
1693 newtop += wheely * 30;
1696 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
1697 if (newleft < 0) newleft = 0;
1699 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
1700 if (newtop < 0) newtop = 0;
1702 if ((newleft != data->view_x) || (newtop != data->view_y))
1704 SetAttrs(obj, MUIA_IconList_Left, newleft,
1705 MUIA_IconList_Top, newtop,
1706 TAG_DONE);
1711 /**************************************************************************
1712 MUIM_HandleEvent
1713 **************************************************************************/
1714 IPTR IconList__MUIM_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
1716 struct MUI_IconData *data = INST_DATA(cl, obj);
1718 if (msg->imsg)
1720 LONG mx = msg->imsg->MouseX - _mleft(obj);
1721 LONG my = msg->imsg->MouseY - _mtop(obj);
1722 LONG wheelx = 0;
1723 LONG wheely = 0;
1725 switch (msg->imsg->Class)
1727 case IDCMP_RAWKEY:
1729 switch(msg->imsg->Code)
1731 case RAWKEY_NM_WHEEL_UP:
1732 wheely = -1;
1733 break;
1735 case RAWKEY_NM_WHEEL_DOWN:
1736 wheely = 1;
1737 break;
1739 case RAWKEY_NM_WHEEL_LEFT:
1740 wheelx = -1;
1741 break;
1743 case RAWKEY_NM_WHEEL_RIGHT:
1744 wheelx = 1;
1745 break;
1749 if (_isinobject(msg->imsg->MouseX, msg->imsg->MouseY) &&
1750 (wheelx || wheely))
1752 DoWheelMove(cl, obj, wheelx, wheely, msg->imsg->Qualifier);
1754 break;
1756 case IDCMP_MOUSEBUTTONS:
1758 if (msg->imsg->Code == SELECTDOWN)
1760 /* check if mouse pressed on iconlist area */
1761 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj))
1763 struct IconEntry *node;
1764 struct IconEntry *new_selected = NULL;
1766 int selections = 0;
1768 data->first_selected = NULL;
1770 /* check if clicked on icon */
1771 node = List_First(&data->icon_list);
1772 while (node)
1774 /* count all OLD selections */
1775 if (node->selected) selections++;
1777 if (mx >= node->x - data->view_x && mx < node->x - data->view_x + node->realWidth &&
1778 my >= node->y - data->view_y && my < node->y - data->view_y + node->realHeight && !new_selected)
1780 new_selected = node;
1782 if (!node->selected)
1784 node->selected = 1;
1785 data->update = UPDATE_SINGLEICON;
1786 data->update_icon = node;
1787 MUI_Redraw(obj,MADF_DRAWUPDATE);
1790 data->first_selected = node;
1793 node = Node_Next(node);
1797 /* if not cliked on icon set lasso as active */
1798 if (!new_selected)
1800 data->lasso_active = TRUE;
1801 data->lasso_rect.MinX = mx - data->view_rect.MinX + data->view_x;
1802 data->lasso_rect.MinY = my - data->view_rect.MinY + data->view_y;
1803 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
1804 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
1806 /* deselect old selection */
1807 DoMethod(obj,MUIM_IconList_UnselectAll);
1809 /* draw initial lasso */
1810 InvertLassoOutlines(obj, &data->lasso_rect);
1813 else
1815 data->lasso_active = FALSE;
1817 /* remove last single selection if clicked on different file*/
1818 if (data->last_selected && new_selected != data->last_selected && selections < 2)
1820 data->last_selected->selected = 0;
1821 data->update = UPDATE_SINGLEICON;
1822 data->update_icon = data->last_selected;
1823 MUI_Redraw(obj,MADF_DRAWUPDATE);
1827 data->icon_click.shift = !!(msg->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT));
1828 data->icon_click.entry = new_selected?&new_selected->entry:NULL;
1829 set(obj,MUIA_IconList_Clicked,(IPTR)&data->icon_click);
1831 if (DoubleClick(data->last_secs, data->last_mics, msg->imsg->Seconds, msg->imsg->Micros) && data->last_selected == new_selected)
1833 set(obj,MUIA_IconList_DoubleClick, TRUE);
1834 data->last_selected = NULL;
1836 else if (!data->mouse_pressed)
1838 data->last_selected = new_selected;
1839 data->last_secs = msg->imsg->Seconds;
1840 data->last_mics = msg->imsg->Micros;
1842 /* After a double click you often open a new window
1843 * and since Zune doesn't not support the faking
1844 * of SELECTUP events only change the Events
1845 * if not doubleclicked */
1847 data->mouse_pressed |= LEFT_BUTTON;
1849 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
1851 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1852 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
1853 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1857 data->click_x = mx;
1858 data->click_y = my;
1860 return 0;
1863 else if (msg->imsg->Code == MIDDLEDOWN)
1865 if (!data->mouse_pressed)
1867 data->mouse_pressed |= MIDDLE_BUTTON;
1869 data->click_x = data->view_x + mx;
1870 data->click_y = data->view_y + my;
1872 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
1874 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1875 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
1876 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1880 else
1882 if (msg->imsg->Code == SELECTUP)
1885 /* check if mose released on iconlist aswell */
1886 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj) && data->lasso_active == FALSE)
1888 struct IconEntry *node;
1889 struct IconEntry *new_selected = NULL;
1891 data->first_selected = NULL;
1893 node = List_First(&data->icon_list);
1894 while (node)
1897 /* unselect all other nodes if mouse released on icon and lasso was not selected during mouse press */
1898 if ( ( node->selected && data->lasso_active == FALSE) &&
1899 ( mx < node->x - data->view_x || mx > node->x - data->view_x + node->realWidth ||
1900 my < node->y - data->view_y || my > node->y - data->view_y + node->realHeight ) )
1903 node->selected = 0;
1904 data->update = UPDATE_SINGLEICON;
1905 data->update_icon = node;
1906 MUI_Redraw(obj,MADF_DRAWUPDATE);
1909 node = Node_Next(node);
1914 /* stop lasso selection/drawing now */
1915 if (data->lasso_active == TRUE)
1917 /* make lasso disappear again */
1918 struct Rectangle old_lasso;
1919 GetAbsoluteLassoRect(data, &old_lasso);
1920 InvertLassoOutlines(obj, &old_lasso);
1922 data->lasso_active = FALSE;
1925 data->mouse_pressed &= ~LEFT_BUTTON;
1928 if (msg->imsg->Code == MIDDLEUP)
1930 data->mouse_pressed &= ~MIDDLE_BUTTON;
1933 if ((data->ehn.ehn_Events & IDCMP_MOUSEMOVE) && !data->mouse_pressed)
1935 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1936 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
1937 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1940 break;
1942 case IDCMP_MOUSEMOVE:
1944 if (data->mouse_pressed & LEFT_BUTTON)
1946 int move_x = mx;
1947 int move_y = my;
1949 /* check if clicked on icon, or update lasso coords if lasso activated */
1950 if (
1951 data->first_selected && data->lasso_active == FALSE &&
1952 (abs(move_x - data->click_x) >= 2 || abs(move_y - data->click_y) >= 2)
1955 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1956 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
1957 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1959 data->mouse_pressed &= ~LEFT_BUTTON;
1961 data->touch_x = move_x + data->view_x - data->first_selected->x;
1962 data->touch_y = move_y + data->view_y - data->first_selected->y;
1963 DoMethod(obj,MUIM_DoDrag, data->touch_x, data->touch_y, 0);
1965 else if (data->lasso_active == TRUE) /* if no icon selected start lasso */
1967 struct Rectangle new_lasso, old_lasso;
1968 struct IconEntry *node;
1969 struct IconEntry *new_selected = NULL;
1971 /* unmark old lasso area */
1972 GetAbsoluteLassoRect(data, &old_lasso);
1973 InvertLassoOutlines(obj, &old_lasso);
1975 /* if mouse leaves iconlist area during lasso mode, scroll view */
1976 if (mx < 0 || mx > _width(obj) || my < 0 || my > _height(obj))
1978 WORD newleft = data->view_x;
1979 WORD newtop = data->view_y;
1981 if (data->click_x < mx) newleft += 5;
1982 else newleft -= 5;
1983 if (data->click_y < my) newtop += 5;
1984 else newtop -= 5;
1986 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
1987 if (newleft < 0) newleft = 0;
1989 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
1990 if (newtop < 0) newtop = 0;
1992 if ((newleft != data->view_x) || (newtop != data->view_y))
1994 SetAttrs(obj, MUIA_IconList_Left, newleft, MUIA_IconList_Top, newtop, TAG_DONE);
1999 /* update lasso coordinates */
2000 data->lasso_rect.MaxX = mx - data->view_rect.MinX + data->view_x;
2001 data->lasso_rect.MaxY = my - data->view_rect.MinY + data->view_y;
2003 /* get absolute lasso coordinates */
2004 GetAbsoluteLassoRect(data, &new_lasso);
2006 data->first_selected = NULL;
2008 node = List_First(&data->icon_list);
2009 while (node)
2012 /* check if clicked on icon */
2013 if (new_lasso.MaxX >= node->x - data->view_x
2014 && new_lasso.MinX < node->x - data->view_x + node->realWidth &&
2015 new_lasso.MaxY >= node->y - data->view_y
2016 && new_lasso.MinY < node->y - data->view_y + node->realHeight)
2018 new_selected = node;
2020 /* check if icon was already selected before */
2021 if (!node->selected)
2023 node->selected = 1;
2024 data->update = UPDATE_SINGLEICON;
2025 data->update_icon = node;
2026 data->last_selected = node; // <- I'm the latest addition to your flock! =)
2027 MUI_Redraw(obj,MADF_DRAWUPDATE);
2030 data->first_selected = node;
2033 else
2035 if (node->selected) /* if not catched by lasso and selected before -> unselect */
2037 node->selected = 0;
2038 data->update = UPDATE_SINGLEICON;
2039 data->update_icon = node;
2040 MUI_Redraw(obj,MADF_DRAWUPDATE);
2044 node = Node_Next(node);
2047 /* set lasso borders */
2048 InvertLassoOutlines(obj, &new_lasso);
2052 return 0;
2054 else if (data->mouse_pressed & MIDDLE_BUTTON)
2056 WORD newleft, newtop;
2058 newleft = data->click_x - mx;
2059 newtop = data->click_y - my;
2061 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
2062 if (newleft < 0) newleft = 0;
2064 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
2065 if (newtop < 0) newtop = 0;
2067 if ((newleft != data->view_x) || (newtop != data->view_y))
2069 SetAttrs(obj, MUIA_IconList_Left, newleft,
2070 MUIA_IconList_Top, newtop,
2071 TAG_DONE);
2074 return 0;
2077 break;
2081 return 0;
2084 /**************************************************************************
2085 MUIM_IconList_NextSelected
2086 **************************************************************************/
2087 IPTR IconList__MUIM_NextSelected(struct IClass *cl, Object *obj, struct MUIP_IconList_NextSelected *msg)
2089 struct MUI_IconData *data = INST_DATA(cl, obj);
2090 struct IconEntry *node;
2091 struct IconList_Entry *ent;
2093 if (!msg->entry) return (IPTR)NULL;
2094 ent = *msg->entry;
2096 if (((IPTR)ent) == MUIV_IconList_NextSelected_Start)
2098 if (!(node = data->last_selected))
2100 D(bug("[IconList] No selected entries!!!\n"));
2101 *msg->entry = (struct IconList_Entry*)MUIV_IconList_NextSelected_End;
2103 else
2105 /* get the first selected entry in list */
2106 node = List_First(&data->icon_list);
2107 while (!node->selected)
2109 node = Node_Next(node);
2112 *msg->entry = &node->entry;
2114 return 0;
2117 node = List_First(&data->icon_list); /* not really necessary but it avoids compiler warnings */
2119 node = (struct IconEntry*)(((char*)ent) - ((char*)(&node->entry) - (char*)node));
2120 node = Node_Next(node);
2122 while (node)
2124 if (node->selected)
2126 *msg->entry = &node->entry;
2127 return 0;
2129 node = Node_Next(node);
2132 *msg->entry = (struct IconList_Entry*)MUIV_IconList_NextSelected_End;
2134 return (IPTR)NULL;
2137 /**************************************************************************
2138 MUIM_CreateDragImage
2139 **************************************************************************/
2140 IPTR IconList__MUIM_CreateDragImage(struct IClass *cl, Object *obj, struct MUIP_CreateDragImage *msg)
2142 struct MUI_IconData *data = INST_DATA(cl, obj);
2143 struct MUI_DragImage *img = NULL;
2145 if (!data->first_selected) DoSuperMethodA(cl,obj,(Msg)msg);
2147 if ((img = (struct MUI_DragImage *)AllocVec(sizeof(struct MUIP_CreateDragImage),MEMF_CLEAR)))
2149 struct IconEntry *node;
2150 LONG depth = GetBitMapAttr(_screen(obj)->RastPort.BitMap,BMA_DEPTH);
2152 node = data->first_selected;
2154 img->width = node->width;
2155 img->height = node->height;
2157 if ((img->bm = AllocBitMap(img->width,img->height,depth,BMF_MINPLANES|BMF_CLEAR,_screen(obj)->RastPort.BitMap)))
2159 struct RastPort temprp;
2160 InitRastPort(&temprp);
2161 temprp.BitMap = img->bm;
2163 #ifndef __AROS__
2164 DrawIconState(&temprp,node->dob,NULL,0,0, node->selected?IDS_SELECTED:IDS_NORMAL, ICONDRAWA_EraseBackground, TRUE, TAG_DONE);
2165 #else
2166 DrawIconStateA(&temprp,node->dob,NULL,0,0, node->selected?IDS_SELECTED:IDS_NORMAL, NULL);
2167 #endif
2168 DeinitRastPort(&temprp);
2171 img->touchx = msg->touchx;
2172 img->touchy = msg->touchy;
2173 img->flags = 0;
2175 return (ULONG)img;
2178 /**************************************************************************
2179 MUIM_DeleteDragImage
2180 **************************************************************************/
2181 IPTR IconList__MUIM_DeleteDragImage(struct IClass *cl, Object *obj, struct MUIP_DeleteDragImage *msg)
2183 struct MUI_IconData *data = INST_DATA(cl, obj);
2185 if (!data->first_selected) return DoSuperMethodA(cl,obj,(Msg)msg);
2187 if (msg->di)
2189 if (msg->di->bm)
2190 FreeBitMap(msg->di->bm);
2191 FreeVec(msg->di);
2193 return (IPTR)NULL;
2196 /**************************************************************************
2197 MUIM_DragQuery
2198 **************************************************************************/
2199 IPTR IconList__MUIM_DragQuery(struct IClass *cl, Object *obj, struct MUIP_DragQuery *msg)
2201 if (msg->obj == obj) return MUIV_DragQuery_Accept;
2202 else
2204 int is_iconlist = 0;
2205 struct IClass *msg_cl = OCLASS(msg->obj);
2207 while (msg_cl)
2209 if (msg_cl == cl)
2211 is_iconlist = 1;
2212 break;
2214 msg_cl = msg_cl->cl_Super;
2216 if (is_iconlist) return MUIV_DragQuery_Accept;
2219 return MUIV_DragQuery_Refuse;
2222 /**************************************************************************
2223 MUIM_DragDrop
2224 **************************************************************************/
2225 IPTR IconList__MUIM_DragDrop(struct IClass *cl, Object *obj, struct MUIP_DragDrop *msg)
2227 struct MUI_IconData *data = INST_DATA(cl, obj);
2229 /* check if dropped on same iconlist object */
2230 if (msg->obj == obj)
2232 struct IconEntry *icon = data->first_selected;
2234 if (icon)
2236 struct Rectangle old, new;
2237 struct Region *region;
2238 APTR clip = NULL;
2240 /* icon moved, dropped in the same window */
2241 set(obj, MUIA_IconList_IconsMoved, (IPTR) &(data->first_selected->entry)); /* Now notify */
2242 D( bug("[ICONLIST] move entry: %s dropped in same window\n", data->first_selected->entry.filename); )
2244 IconList_GetIconRectangle(obj, data, icon, &old);
2246 old.MinX += _mleft(obj) - data->view_x + icon->x;
2247 old.MaxX += _mleft(obj) - data->view_x + icon->x;
2248 old.MinY += _mtop(obj) - data->view_y + icon->y;
2249 old.MaxY += _mtop(obj) - data->view_y + icon->y;
2251 icon->x = msg->x - _mleft(obj) + data->view_x - data->touch_x;
2252 icon->y = msg->y - _mtop(obj) + data->view_y - data->touch_y;
2254 IconList_RethinkDimensions(obj, data, data->first_selected);
2256 IconList_GetIconRectangle(obj, data, data->first_selected, &new);
2258 new.MinX += _mleft(obj) - data->view_x + icon->x;
2259 new.MaxX += _mleft(obj) - data->view_x + icon->x;
2260 new.MinY += _mtop(obj) - data->view_y + icon->y;
2261 new.MaxY += _mtop(obj) - data->view_y + icon->y;
2263 region = NewRegion();
2264 if (region)
2266 OrRectRegion(region, &old);
2267 OrRectRegion(region, &new);
2268 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
2271 MUI_Redraw(obj,MADF_DRAWOBJECT);
2273 if (region)
2275 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
2280 else
2283 struct IconEntry *icon;
2284 struct IconList_Entry *entry = (APTR) MUIV_IconList_NextSelected_Start;
2286 /* get selected entries from SOURCE iconlist */
2287 DoMethod(msg->obj, MUIM_IconList_NextSelected, (IPTR) &entry);
2289 /* check if dropped on an icon on the iconlist area */
2290 if (entry)
2293 /* check if dropped on a drawer */
2294 struct IconEntry *node;
2295 struct IconEntry *drop_target_node = NULL;
2297 /* go through list and check if dropped on icon */
2298 node = List_First(&data->icon_list);
2299 while (node)
2301 if (msg->x >= node->x - data->view_x &&
2302 msg->x < node->x - data->view_x + node->realWidth &&
2303 msg->y >= node->y - data->view_y + _mtop(obj) &&
2304 msg->y < node->y - data->view_y + node->realHeight + _mtop(obj) && !drop_target_node)
2306 drop_target_node = node;
2309 node = Node_Next(node);
2313 /* get path to destination directory */
2314 STRPTR directory_path = XGET(obj, MUIA_IconDrawerList_Drawer);
2316 /* check if dropped on a root drive -
2317 last condition is a hack, based upon another hack (adding ":Disk" to rootdrive name)
2318 since ST_ROOT seems not to be set properly right now (?) */
2319 if (drop_target_node && ( drop_target_node->entry.type == ST_ROOT
2320 || ( !strcmp(drop_target_node->entry.filename+strlen(drop_target_node->entry.filename)-5,":Disk") ) ) )
2322 int tmplen = 0;
2324 /* avoid copying "Disk" (hack anyway?!) from root drive name, eg. "Ram Disk:Disk"*/
2325 tmplen = strlen(drop_target_node->entry.filename) - 4;
2327 /* copy path of dir icon dropped on */
2328 strncpy(data->drop_entry.destination_string, drop_target_node->entry.filename, tmplen);
2330 /* mark the drive the icon was dropped on*/
2331 drop_target_node->selected = 1;
2332 data->update = UPDATE_SINGLEICON;
2333 data->update_icon = drop_target_node;
2334 MUI_Redraw(obj,MADF_DRAWUPDATE);
2336 D( bug("[ICONLIST] drop entry: %s dropped on disk icon %s\n", entry->filename, drop_target_node->entry.filename); )
2338 /* check if dropped on a drawer icon in iconlist */
2339 else if (drop_target_node && drop_target_node->entry.type == ST_USERDIR )
2341 /* copy path of dir icon dropped on */
2342 strcpy(data->drop_entry.destination_string, drop_target_node->entry.filename);
2344 /* mark the directory the icon was dropped on*/
2345 drop_target_node->selected = 1;
2346 data->update = UPDATE_SINGLEICON;
2347 data->update_icon = drop_target_node;
2348 MUI_Redraw(obj,MADF_DRAWUPDATE);
2350 D( bug("[ICONLIST] drop entry: %s dropped on dir %s icon in window %s\n", entry->filename, drop_target_node->entry.filename, directory_path); )
2352 else
2354 /* not dropped on icon -> get path of DESTINATION iconlist */
2355 D( bug("[ICONLIST] drop entry: %s dropped in window %s\n", entry->filename, directory_path); )
2356 /* copy path */
2357 strcpy(data->drop_entry.destination_string, directory_path);
2360 /* copy relevant data to drop entry */
2361 data->drop_entry.source_iconlistobj = (IPTR)msg->obj;
2362 data->drop_entry.destination_iconlistobj = (IPTR)obj;
2364 /* return drop entry */
2365 set(obj, MUIA_IconList_IconsDropped, (IPTR)&data->drop_entry); /* Now notify */
2367 else
2369 /* no drop entry */
2370 set(obj, MUIA_IconList_IconsDropped, (IPTR)NULL); /* Now notify */
2374 return DoSuperMethodA(cl,obj,(Msg)msg);
2377 /**************************************************************************
2378 MUIM_UnselectAll
2379 **************************************************************************/
2380 IPTR IconList__MUIM_UnselectAll(struct IClass *cl, Object *obj, Msg msg)
2382 struct MUI_IconData *data = INST_DATA(cl, obj);
2383 struct IconEntry *node;
2385 node = List_First(&data->icon_list);
2386 while (node)
2388 if (node->selected)
2390 node->selected = 0;
2391 data->update = UPDATE_SINGLEICON;
2392 data->update_icon = node;
2393 MUI_Redraw(obj,MADF_DRAWUPDATE);
2395 node = Node_Next(node);
2397 data->first_selected = NULL;
2398 data->last_selected = NULL;
2399 return 1;
2402 /**************************************************************************
2403 MUIM_SelectAll
2404 **************************************************************************/
2405 IPTR IconList__MUIM_SelectAll(struct IClass *cl, Object *obj, Msg msg)
2407 struct MUI_IconData *data = INST_DATA(cl, obj);
2408 struct IconEntry *node;
2410 node = List_First(&data->icon_list);
2411 data->first_selected = node;
2412 while (node)
2414 if (!node->selected)
2416 node->selected = 1;
2417 data->update = UPDATE_SINGLEICON;
2418 data->update_icon = node;
2419 data->last_selected = node;
2420 MUI_Redraw(obj,MADF_DRAWUPDATE);
2422 node = Node_Next(node);
2425 return 1;
2428 struct MUI_IconDrawerData
2430 char *drawer;
2433 /**************************************************************************
2434 Read icons in
2435 **************************************************************************/
2436 static int ReadIcons(struct IClass *cl, Object *obj)
2438 struct MUI_IconDrawerData *data = INST_DATA(cl, obj);
2439 BPTR lock;
2440 char filename[256];
2442 if (!data->drawer)
2443 return 1;
2445 lock = Lock(data->drawer, SHARED_LOCK);
2447 if (lock)
2449 struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, NULL);
2450 if (fib)
2452 if (Examine(lock, fib))
2454 while(ExNext(lock, fib))
2456 int len;
2458 strcpy(filename,fib->fib_FileName);
2459 len = strlen(filename);
2461 if (len >= 5)
2463 /* reject all .info files, so we have a Show All mode */
2464 if (!Stricmp(&filename[len-5],".info"))
2465 continue;
2468 if (Stricmp(filename,"Disk")) /* skip disk.info */
2470 char buf[ 512 ];
2471 strcpy(buf,data->drawer);
2472 AddPart(buf,filename,sizeof(buf));
2473 DoMethod(obj,MUIM_IconList_Add,(IPTR)buf,(IPTR)filename,(IPTR) fib);
2478 FreeDosObject(DOS_FIB, fib);
2481 UnLock(lock);
2484 return 1;
2488 static int OLDReadIcons(struct IClass *cl, Object *obj)
2490 struct MUI_IconDrawerData *data = INST_DATA(cl, obj);
2491 BPTR lock;
2493 struct ExAllControl *eac;
2494 struct ExAllData *entry;
2495 void *ead;
2496 LONG more;
2497 BPTR olddir;
2498 //char pattern[40];
2499 char filename[256];
2501 if (!data->drawer) return 1;
2502 lock = Lock(data->drawer,ACCESS_READ);
2503 if (!lock) return 0;
2505 eac = (struct ExAllControl*)AllocDosObject(DOS_EXALLCONTROL,NULL);
2506 if (!eac)
2508 UnLock(lock);
2509 return 0;
2512 ead = AllocVec(1024,0);
2513 if (!ead)
2515 FreeDosObject(DOS_EXALLCONTROL,eac);
2516 UnLock(lock);
2517 return 0;
2520 *//*
2521 ParsePatternNoCase("#?.info",pattern,sizeof(pattern));
2522 eac->eac_MatchString = pattern;
2523 *//*
2524 #ifdef __AROS__
2525 #warning AROS ExAll() doesnt support eac_MatchString
2526 #endif
2527 eac->eac_MatchString = NULL;
2528 eac->eac_LastKey = 0;
2530 olddir = CurrentDir(lock);
2534 more = ExAll(lock,ead,1024,ED_TYPE,eac);
2535 if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) break;
2536 if (eac->eac_Entries == 0) continue;
2538 entry = (struct ExAllData*)ead;
2541 int len;
2543 strcpy(filename,entry->ed_Name);
2545 *//*
2546 // if we only display icons
2548 filename[strlen(filename)-5]=0;
2549 *//*
2550 len = strlen(filename);
2551 if (len >= 5)
2553 *//* reject all .info files, so we have a Show All mode *//*
2554 if (!Stricmp(&filename[len-5],".info"))
2555 continue;
2558 if (Stricmp(filename,"Disk")) *//* skip disk.info *//*
2560 char buf[512];
2561 strcpy(buf,data->drawer);
2562 AddPart(buf,filename,sizeof(buf));
2564 if (!(DoMethod(obj,MUIM_IconList_Add,(IPTR)buf,(IPTR)filename,entry->ed_Type,NULL *//* udata *//*)))
2568 } while ((entry = entry->ed_Next));
2569 } while (more);
2571 CurrentDir(olddir);
2573 FreeVec(ead);
2574 FreeDosObject(DOS_EXALLCONTROL,eac);
2575 UnLock(lock);
2576 return 1;
2580 /**************************************************************************
2581 MUIM_Sort - sortsort
2582 **************************************************************************/
2583 IPTR IconList__MUIM_Sort(struct IClass *cl, Object *obj, struct MUIP_IconList_Sort *msg)
2585 struct MUI_IconData *data = INST_DATA(cl, obj);
2586 struct IconEntry *entry,*icon1,*icon2;
2587 struct MinList list;
2588 int sortme;
2589 int i;
2591 NewList((struct List*)&list);
2593 /*move list int out local list struct*/
2594 while( (entry = (struct IconEntry *)RemTail((struct List*)&data->icon_list)) )
2595 AddHead( (struct List*)&list , (struct Node *)entry );
2597 /*now copy each one back to the main list, sorting as we go*/
2598 entry = List_First(&list);
2600 while((entry = (struct IconEntry *)RemTail((struct List*)&list)))
2602 icon1 = List_First(&data->icon_list);
2603 icon2 = NULL;
2604 sortme = 0;
2606 /*D(bug(" - %s %s %s %i\n",entry->entry.label,entry->datebuf,entry->timebuf,entry->fib.fib_Size));*/
2608 while( icon1 )
2611 /*drawers mixed*/
2612 if( data->sort_bits & ICONLIST_SORT_DRAWERS_MIXED )
2614 sortme = 1;
2616 else
2617 /*drawers first*/
2619 if( icon1->entry.type == WBDRAWER && entry->entry.type == WBDRAWER )
2621 sortme = 1;
2623 else
2625 if( icon1->entry.type != WBDRAWER && entry->entry.type != WBDRAWER )
2626 sortme = 1;
2627 else
2629 /*we are the first drawer to arrive or we need to insert ourselves due to being sorted to the end of the drawers*/
2630 if( (!icon2 || icon2->entry.type == WBDRAWER) && entry->entry.type == WBDRAWER && icon1->entry.type != WBDRAWER )
2632 /*D(bug("force %s\n"),entry->entry.label);*/
2633 break;
2639 if(sortme)
2641 i = 0;
2643 /*date*/
2644 if( (data->sort_bits & ICONLIST_SORT_BY_DATE) && !(data->sort_bits & ICONLIST_SORT_BY_SIZE) )
2646 i = CompareDates((const struct DateStamp *)&entry->fib.fib_Date,(const struct DateStamp *)&icon1->fib.fib_Date);
2647 /*D(bug(" - %i\n",i));*/
2649 else
2651 /*size*/
2652 if( (data->sort_bits & ICONLIST_SORT_BY_SIZE) && !(data->sort_bits & ICONLIST_SORT_BY_DATE) )
2654 i = entry->fib.fib_Size - icon1->fib.fib_Size;
2655 /*D(bug(" - %i\n",i));*/
2658 else
2659 /*type*/
2660 if( data->sort_bits & (ICONLIST_SORT_BY_DATE | ICONLIST_SORT_BY_SIZE) )
2664 else
2665 /*name*/
2667 i = Stricmp(entry->entry.label,icon1->entry.label);
2671 if ( !(data->sort_bits & ICONLIST_SORT_REVERSE) && i<0 )
2672 break;
2674 if ( (data->sort_bits & ICONLIST_SORT_REVERSE) && i>0)
2675 break;
2680 icon2 = icon1;
2681 icon1 = Node_Next( icon1 );
2684 Insert( (struct List*)&data->icon_list , (struct Node *)entry , (struct Node *)icon2 );
2687 /*debug, stomp it back in in reverse order instead
2688 while( (entry = (struct IconEntry *)RemTail((struct List*)&list)) )
2689 AddTail( (struct List*)&data->icon_list , (struct Node *)entry );
2692 DoMethod(obj,MUIM_IconList_PositionIcons);
2693 MUI_Redraw(obj,MADF_DRAWOBJECT);
2695 return 1;
2698 /**************************************************************************
2699 MUIM_SetSortBits - set our sorting bits
2700 **************************************************************************/
2701 IPTR IconList__MUIM_SetSortBits(struct IClass *cl, Object *obj, struct MUIP_IconList_SetSortBits *msg)
2703 struct MUI_IconData *data = INST_DATA(cl, obj);
2704 data->sort_bits = msg->sort_bits;
2705 return 1;
2708 /**************************************************************************
2709 MUIM_GetSortBits - return our sorting bits
2710 **************************************************************************/
2711 IPTR IconList__MUIM_GetSortBits(struct IClass *cl, Object *obj, struct MUIP_IconList_GetSortBits *msg)
2713 struct MUI_IconData *data = INST_DATA(cl, obj);
2714 return data->sort_bits;
2717 /**************************************************************************
2718 MUIM_DragReport. Since MUI doesn't change the drop object if the dragged
2719 object is moved above another window (while still in the bounds of the
2720 orginal drop object) we must do it here manually to be compatible with
2721 MUI. Maybe Zune should fix this bug somewhen.
2722 **************************************************************************/
2723 IPTR IconList__MUIM_DragReport(struct IClass *cl, Object *obj, struct MUIP_DragReport *msg)
2725 struct Window *wnd = _window(obj);
2726 struct Layer *l;
2728 l = WhichLayer(&wnd->WScreen->LayerInfo, wnd->LeftEdge + msg->x, wnd->TopEdge + msg->y);
2729 if (l != wnd->WLayer) return MUIV_DragReport_Abort;
2730 return MUIV_DragReport_Continue;
2733 /**************************************************************************
2734 MUIM_IconList_UnknownDropDestination
2735 **************************************************************************/
2737 IPTR IconList__MUIM_UnknownDropDestination(struct IClass *cl, Object *obj, struct MUIP_UnknownDropDestination *msg)
2739 D(bug("[ICONLIST] icons dropped on custom window \n");)
2740 set(obj, MUIA_IconList_AppWindowDrop, (IPTR)msg); /* Now notify */
2742 return 0;
2745 /*************************************************************************/
2747 BOOPSI_DISPATCHER(IPTR,IconList_Dispatcher, cl, obj, msg)
2749 switch (msg->MethodID)
2751 case OM_NEW: return IconList__OM_NEW(cl, obj, (struct opSet *)msg);
2752 case OM_DISPOSE: return IconList__OM_DISPOSE(cl,obj, msg);
2753 case OM_SET: return IconList__OM_SET(cl,obj,(struct opSet *)msg);
2754 case OM_GET: return IconList__OM_GET(cl,obj,(struct opGet *)msg);
2756 case MUIM_Setup: return IconList__MUIM_Setup(cl,obj,(struct MUIP_Setup *)msg);
2758 case MUIM_Show: return IconList__MUIM_Show(cl,obj,(struct MUIP_Show *)msg);
2759 case MUIM_Cleanup: return IconList__MUIM_Cleanup(cl,obj,(struct MUIP_Cleanup *)msg);
2760 case MUIM_AskMinMax: return IconList__MUIM_AskMinMax(cl,obj,(struct MUIP_AskMinMax *)msg);
2761 case MUIM_Draw: return IconList__MUIM_Draw(cl,obj,(struct MUIP_Draw *)msg);
2762 case MUIM_Layout: return IconList__MUIM_Layout(cl,obj,(struct MUIP_Layout *)msg);
2763 case MUIM_HandleEvent: return IconList__MUIM_HandleEvent(cl,obj,(struct MUIP_HandleEvent *)msg);
2764 case MUIM_CreateDragImage: return IconList__MUIM_CreateDragImage(cl,obj,(APTR)msg);
2765 case MUIM_DeleteDragImage: return IconList__MUIM_DeleteDragImage(cl,obj,(APTR)msg);
2766 case MUIM_DragQuery: return IconList__MUIM_DragQuery(cl,obj,(APTR)msg);
2767 case MUIM_DragReport: return IconList__MUIM_DragReport(cl,obj,(APTR)msg);
2768 case MUIM_DragDrop: return IconList__MUIM_DragDrop(cl,obj,(APTR)msg);
2769 case MUIM_UnknownDropDestination: return IconList__MUIM_UnknownDropDestination(cl,obj,(APTR)msg);
2770 case MUIM_IconList_Update: return IconList__MUIM_Update(cl,obj,(APTR)msg);
2771 case MUIM_IconList_Clear: return IconList__MUIM_Clear(cl,obj,(APTR)msg);
2772 case MUIM_IconList_Add: return IconList__MUIM_Add(cl,obj,(APTR)msg);
2773 case MUIM_IconList_NextSelected: return IconList__MUIM_NextSelected(cl,obj,(APTR)msg);
2774 case MUIM_IconList_UnselectAll: return IconList__MUIM_UnselectAll(cl,obj,(APTR)msg);
2775 case MUIM_IconList_Sort: return IconList__MUIM_Sort(cl,obj,(APTR)msg);
2776 case MUIM_IconList_GetSortBits: return IconList__MUIM_GetSortBits(cl,obj,(APTR)msg);
2777 case MUIM_IconList_SetSortBits: return IconList__MUIM_SetSortBits(cl,obj,(APTR)msg);
2778 case MUIM_IconList_PositionIcons: return IconList__MUIM_PositionIcons(cl,obj,(APTR)msg);
2779 case MUIM_IconList_SelectAll: return IconList__MUIM_SelectAll(cl,obj,(APTR)msg);
2782 return DoSuperMethodA(cl, obj, msg);
2784 BOOPSI_DISPATCHER_END
2787 /**************************************************************************
2788 OM_NEW
2789 **************************************************************************/
2790 IPTR IconDrawerList__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2792 struct MUI_IconDrawerData *data;
2793 struct TagItem *tag, *tags;
2795 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
2796 TAG_MORE, (IPTR) msg->ops_AttrList);
2797 if (!obj) return FALSE;
2799 data = INST_DATA(cl, obj);
2801 /* parse initial taglist */
2802 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
2804 switch (tag->ti_Tag)
2806 case MUIA_IconDrawerList_Drawer:
2807 data->drawer = StrDup((char*)tag->ti_Data);
2808 break;
2812 return (IPTR)obj;
2815 /**************************************************************************
2816 OM_DISPOSE
2817 **************************************************************************/
2818 IPTR IconDrawerList__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2820 struct MUI_IconDrawerData *data = INST_DATA(cl, obj);
2822 if (data->drawer) FreeVec(data->drawer);
2823 return DoSuperMethodA(cl,obj,msg);
2826 /**************************************************************************
2827 OM_SET
2828 **************************************************************************/
2829 IPTR IconDrawerList__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
2831 struct MUI_IconDrawerData *data = INST_DATA(cl, obj);
2832 struct TagItem *tag, *tags;
2834 /* parse initial taglist */
2835 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
2837 switch (tag->ti_Tag)
2839 case MUIA_IconDrawerList_Drawer:
2840 if (data->drawer) FreeVec(data->drawer);
2841 data->drawer = StrDup((char*)tag->ti_Data);
2842 DoMethod(obj,MUIM_IconList_Update);
2843 break;
2847 return DoSuperMethodA(cl, obj, (Msg)msg);
2850 /**************************************************************************
2851 OM_GET
2852 **************************************************************************/
2853 IPTR IconDrawerList__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
2855 /* small macro to simplify return value storage */
2856 #define STORE *(msg->opg_Storage)
2857 struct MUI_IconDrawerData *data = INST_DATA(cl, obj);
2859 switch (msg->opg_AttrID)
2861 case MUIA_IconDrawerList_Drawer: STORE = (unsigned long)data->drawer; return 1;
2864 if (DoSuperMethodA(cl, obj, (Msg) msg)) return 1;
2865 return 0;
2866 #undef STORE
2869 /**************************************************************************
2870 MUIM_IconList_Update
2871 **************************************************************************/
2872 IPTR IconDrawerList__MUIM_Update(struct IClass *cl, Object *obj, struct MUIP_IconList_Update *msg)
2874 //struct MUI_IconDrawerData *data = INST_DATA(cl, obj);
2875 //struct IconEntry *node;
2876 // struct MUI_IconData *data = INST_DATA(cl, obj);
2878 DoMethod(obj,MUIM_IconList_Clear);
2880 /* If not in setup do nothing */
2881 if (!(_flags(obj)&MADF_SETUP)) return 1;
2882 ReadIcons(cl,obj);
2884 /*_Sort takes care of icon placement and redrawing for us*/
2885 DoMethod(obj,MUIM_IconList_Sort);
2886 return 1;
2890 BOOPSI_DISPATCHER(IPTR, IconDrawerList_Dispatcher, cl, obj, msg)
2892 switch (msg->MethodID)
2894 case OM_NEW: return IconDrawerList__OM_NEW(cl, obj, (struct opSet *)msg);
2895 case OM_DISPOSE: return IconDrawerList__OM_DISPOSE(cl,obj,msg);
2896 case OM_SET: return IconDrawerList__OM_SET(cl, obj, (struct opSet *)msg);
2897 case OM_GET: return IconDrawerList__OM_GET(cl, obj, (struct opGet *)msg);
2898 case MUIM_IconList_Update: return IconDrawerList__MUIM_Update(cl,obj,(APTR)msg);
2900 return DoSuperMethodA(cl, obj, msg);
2902 BOOPSI_DISPATCHER_END
2904 /* sba: taken from SimpleFind3 */
2906 struct NewDosList
2908 struct MinList list;
2909 APTR pool;
2912 struct NewDosNode
2914 struct MinNode node;
2915 STRPTR name;
2916 STRPTR device;
2917 struct MsgPort *port;
2920 static struct NewDosList *DosList_Create(void)
2922 APTR pool = CreatePool(MEMF_PUBLIC,4096,4096);
2923 if (pool)
2925 struct NewDosList *ndl = (struct NewDosList*)AllocPooled(pool,sizeof(struct NewDosList));
2926 if (ndl)
2928 struct DosList *dl;
2930 NewList((struct List*)ndl);
2931 ndl->pool = pool;
2933 dl = LockDosList(LDF_VOLUMES|LDF_READ);
2934 while(( dl = NextDosEntry(dl, LDF_VOLUMES)))
2936 STRPTR name;
2937 #ifndef __AROS__
2938 UBYTE *dosname = (UBYTE*)BADDR(dl->dol_Name);
2939 LONG len = dosname[0];
2940 dosname++;
2941 #else
2942 UBYTE *dosname = dl->dol_DevName;
2943 LONG len = strlen(dosname);
2944 #endif
2946 if ((name = (STRPTR)AllocPooled(pool, len+1)))
2948 struct NewDosNode *ndn;
2950 name[len] = 0;
2951 strncpy(name,dosname,len);
2953 if ((ndn = (struct NewDosNode*)AllocPooled(pool, sizeof(*ndn))))
2955 D(bug("[Wanderer]: DosList_Create: adding node for '%s'\n", name));
2956 ndn->name = name;
2957 ndn->device = NULL;
2958 #ifndef __AROS__
2959 ndn->port = dl->dol_Task;
2960 #else
2961 ndn->port = NULL;
2962 #endif
2965 struct IOStdReq *vol_tmp_ioreq=NULL;
2966 struct MsgPort *vol_tmp_mp=NULL;
2968 mp = CreateMsgPort();
2969 if (mp)
2971 ioreq = (struct IOStdReq *)CreateIORequest(mp, sizeof(struct IOStdReq));
2972 if (ioreq)
2974 ioreq->iotd_Req.io_Length = sizeof(struct Interrupt);
2975 ioreq->iotd_Req.io_Data = (APTR)Wanderer_VolumeInterrupt;
2976 ioreq->iotd_Req.io_Command = TD_ADDCHANGEINT;
2977 SendIO((struct IORequest *)DiskIO);
2979 } */
2981 AddTail((struct List*)ndl,(struct Node*)ndn);
2985 UnLockDosList(LDF_VOLUMES|LDF_READ);
2987 #ifndef __AROS__
2988 dl = LockDosList(LDF_DEVICES|LDF_READ);
2989 while(( dl = NextDosEntry(dl, LDF_DEVICES)))
2991 struct NewDosNode *ndn;
2993 if (!dl->dol_Task) continue;
2995 ndn = (struct NewDosNode*)List_First(ndl);
2996 while ((ndn))
2998 if (dl->dol_Task == ndn->port)
3000 STRPTR name;
3001 UBYTE *dosname = (UBYTE*)BADDR(dl->dol_Name);
3002 LONG len = dosname[0];
3004 if ((name = (STRPTR)AllocPooled(pool, len+1)))
3006 name[len] = 0;
3007 strncpy(name,&dosname[1],len);
3010 ndn->device = name;
3011 break;
3014 ndn = (struct NewDosNode*)Node_Next(ndn);
3017 UnLockDosList(LDF_DEVICES|LDF_READ);
3018 #endif
3020 return ndl;
3022 DeletePool(pool);
3024 return NULL;
3027 static void DosList_Dispose(struct NewDosList *ndl)
3029 if (ndl && ndl->pool) DeletePool(ndl->pool);
3031 /* sba: End SimpleFind3 */
3034 struct MUI_IconVolumneData
3036 int dummy;
3039 /**************************************************************************
3040 OM_NEW
3041 **************************************************************************/
3042 IPTR IconVolumeList__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
3044 struct MUI_IconDrawerData *data;
3045 struct TagItem *tag, *tags;
3047 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
3048 TAG_MORE, (IPTR) msg->ops_AttrList);
3049 if (!obj) return FALSE;
3051 data = INST_DATA(cl, obj);
3053 /* parse initial taglist */
3054 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
3056 switch (tag->ti_Tag)
3061 return (IPTR)obj;
3064 /**************************************************************************
3065 MUIM_IconList_Update
3066 **************************************************************************/
3067 IPTR IconVolumeList__MUIM_Update(struct IClass *cl, Object *obj, struct MUIP_IconList_Update *msg)
3069 //struct MUI_IconVolumeData *data = INST_DATA(cl, obj);
3070 //struct IconEntry *node;
3071 struct NewDosList *ndl;
3072 DoMethod(obj,MUIM_IconList_Clear);
3074 /* If not in setup do nothing */
3075 if (!(_flags(obj)&MADF_SETUP)) return 1;
3077 if ((ndl = DosList_Create()))
3079 struct NewDosNode *nd = List_First(ndl);
3080 while (nd)
3082 char buf[300];
3083 if (nd->name)
3085 strcpy(buf,nd->name);
3086 strcat(buf,":Disk");
3088 if (!(DoMethod(obj,MUIM_IconList_Add,(IPTR)buf,(IPTR)nd->name, (IPTR)NULL)))
3093 nd = Node_Next(nd);
3095 DosList_Dispose(ndl);
3098 /*deault display bits*/
3099 ULONG sort_bits = ICONLIST_DISP_VERTICAL;
3101 DoMethod(obj,MUIM_IconList_SetSortBits,sort_bits);
3102 DoMethod(obj,MUIM_IconList_Sort);
3104 return 1;
3108 BOOPSI_DISPATCHER(IPTR, IconVolumeList_Dispatcher, cl, obj, msg)
3110 switch (msg->MethodID)
3112 case OM_NEW: return IconVolumeList__OM_NEW(cl, obj, (struct opSet *)msg);
3113 case MUIM_IconList_Update: return IconVolumeList__MUIM_Update(cl,obj,(APTR)msg);
3116 return DoSuperMethodA(cl, obj, msg);
3118 BOOPSI_DISPATCHER_END
3121 * Class descriptor.
3123 const struct __MUIBuiltinClass _MUI_IconList_desc = {
3124 MUIC_IconList,
3125 MUIC_Area,
3126 sizeof(struct MUI_IconData),
3127 (void*)IconList_Dispatcher
3130 const struct __MUIBuiltinClass _MUI_IconDrawerList_desc = {
3131 MUIC_IconDrawerList,
3132 MUIC_IconList,
3133 sizeof(struct MUI_IconDrawerData),
3134 (void*)IconDrawerList_Dispatcher
3137 const struct __MUIBuiltinClass _MUI_IconVolumeList_desc = {
3138 MUIC_IconVolumeList,
3139 MUIC_IconList,
3140 sizeof(struct MUI_IconVolumneData),
3141 (void*)IconVolumeList_Dispatcher