3 // ©1996-2000 Henrik Isaksson
10 UWORD
PM_ItemHeight(struct PM_Window
*a
, struct PopupMenu
*pm
)
12 UWORD r
,fonty
=a
->p
->MenuFont
->tf_YSize
;
14 if(pm
->Flags
&NPM_HBAR_BIT
) {
15 r
=(UWORD
)(PM_Prefs
->pmp_YSpace
*2+5);
16 pm
->Flags
|=NPM_FIXEDSIZE
;
17 } else if(pm
->Flags
&NPM_WIDE_BAR_BIT
) {
18 r
=(UWORD
)(PM_Prefs
->pmp_YOffset
*2+5);
19 pm
->Flags
|=NPM_FIXEDSIZE
;
23 if(pm
->Images
[0]) { if(pm
->Images
[0]->Height
>r
) r
=(UWORD
)pm
->Images
[0]->Height
+1; }
24 if(pm
->Images
[1]) { if(pm
->Images
[1]->Height
>r
) r
=(UWORD
)pm
->Images
[1]->Height
+1; }
27 UBYTE x
=PM_Image_Height(a
->p
, PMIMG_SUBMENU
, pm
);
29 } else if(pm
->Flags
&NPM_CHECKIT
) {
30 UBYTE x
=PM_Image_Height(a
->p
, pm
->Exclude
?PMIMG_EXCLUDE
:PMIMG_CHECKMARK
, pm
);
34 UBYTE x
=PM_Image_Height(a
->p
, PMIMG_AMIGAKEY
, pm
);
38 r
+=(UWORD
)PM_Prefs
->pmp_YSpace
*2; // *2
44 UWORD
PM_ItemWidth(struct PM_Window
*a
, struct PopupMenu
*pm
)
46 UWORD tmp
=0,img
=0,icn
=0,fontx
;
47 struct RastPort tmprp
;
49 fontx
=a
->p
->MenuFont
->tf_XSize
;
50 CopyMem(a
->p
->RootWnd
->RPort
, &tmprp
, sizeof(struct RastPort
));
51 tmprp
.Font
=a
->p
->MenuFont
;
54 if(GET_TXTMODE(pm
)==NPX_TXTBOOPSI
) {
56 STRPTR title
=pm
->Title
;
57 IPTR args
[] = {(IPTR
)pm
->TitleID
, 123};
58 if(GET_TXTMODE(pm
)==NPX_TXTLOCALE
) title
=(STRPTR
)CallHookA(a
->p
->LocaleHook
, (Object
*)pm
, args
);
60 if(title
) tmp
=TextLength(&tmprp
,title
,strlen(title
));
64 if(pm
->Flags
&NPM_CHECKIT
) {
65 tmp
+=PM_Image_Width(a
->p
, pm
->Exclude
?PMIMG_EXCLUDE
:PMIMG_CHECKMARK
, pm
);
66 tmp
+=PM_Prefs
->pmp_Intermediate
;
67 } else if(pm
->Sub
&& (a
->p
->PullDown
==0) && (pm
->Layout
==0)) {
68 tmp
+=PM_Image_Width(a
->p
, PMIMG_SUBMENU
, pm
);
69 tmp
+=PM_Prefs
->pmp_Intermediate
;
73 tmp
+=PM_Image_Width(a
->p
, PMIMG_AMIGAKEY
, pm
);
74 tmp
+=PM_Prefs
->pmp_Intermediate
+fontx
*4;
77 if(pm
->Flags
&NPM_ISIMAGE
) {
78 if(pm
->Images
[0]) img
=pm
->Images
[0]->Width
;
79 if(pm
->Images
[1]) if(pm
->Images
[1]->Width
>img
) img
=pm
->Images
[1]->Width
;
83 struct Image
*img
=pm
->Images
[0];
87 if(!img
) { img
=pm
->Images
[1]; }
88 else if(pm
->Images
[1]) {
89 if(img
->Width
<pm
->Images
[1]->Width
) img
=pm
->Images
[1];
92 tmp
+=PM_Prefs
->pmp_Intermediate
;
94 icn
=img
->Width
+PM_Prefs
->pmp_Intermediate
;
96 if(icn
>a
->IconColumn
) a
->IconColumn
=icn
;
100 if(pm
->Flags
&NPM_COLOURBOX
) {
101 if(!tmp
) { // If there's no other stuff in the item, no intermediate spacing is req'd
103 tmp
-=PM_Prefs
->pmp_XSpace
+2; // Must be like this for some unknow reason...
105 tmp
+=PM_Prefs
->pmp_Intermediate
+fontx
*3;
109 tmp
+=PM_Prefs
->pmp_XSpace
*2; // "Horizontal spacing"
111 tmp
+=2; // Item border
117 void PM_CalcItemSize(struct PM_Window
*a
, struct PopupMenu
*pm
)
125 if(pm
->Flags
& NPM_HIDDEN
) {
129 if(pm
->Flags
& NPM_GROUP
) {
131 // Calculate minimum size for each item.
132 // Calculate total size for the group.
139 PM_CalcItemSize(a
, p
);
141 if(!(p
->Flags
& NPM_HIDDEN
)) {
142 if(pm
->Layout
==PML_Vertical
) {
144 if(p
->Width
>tmpw
) tmpw
=p
->Width
;
147 if(pm
->Layout
==PML_Horizontal
) {
149 if(p
->Height
>tmph
) tmph
=p
->Height
;
157 struct PopupMenu
*tmppm
;
164 if((tmppm
->Flags
&NPM_NOSELECT
) && (tmppm
->Flags
&NPM_SHADOWED
) && !(tmppm
->Flags
&NPM_DISABLED
) && (tmppm
->Next
->Flags
&NPM_WIDE_BAR
)) {
165 //PATCH(TP_CENTER, NPM_CENTERED);
167 PATCH(PMP_TITLE_UNDERLINE
, NPM_UNDERLINEDTEXT
);
168 PATCH(PMP_TITLE_BOLD
, NPM_BOLDTEXT
);
169 PATCH(PMP_TITLE_SHADOW
, NPM_SHADOWED
);
170 PATCH(PMP_TITLE_EMBOSS
, NPM_EMBOSSED
);
171 PATCH(PMP_TITLE_OUTLINE
, NPM_OUTLINED
);
173 //PATCH(TP_SHINE, NPM_SHINETEXT);
174 //PATCH(TP_SHADOW, NPM_SHADOWTEXT);
175 //PATCH(TP_HILITE, NPM_HILITETEXT);
183 //TPATCH(TP_CENTER, NPM_CENTERED);
185 TPATCH(PMP_TEXT_UNDERLINE
, NPM_UNDERLINEDTEXT
);
186 TPATCH(PMP_TEXT_BOLD
, NPM_BOLDTEXT
);
187 TPATCH(PMP_TEXT_SHADOW
, NPM_SHADOWED
);
188 TPATCH(PMP_TEXT_EMBOSS
, NPM_EMBOSSED
);
189 TPATCH(PMP_TEXT_OUTLINE
, NPM_OUTLINED
);
191 //TPATCH(TP_SHINE, NPM_SHINETEXT);
192 //TPATCH(TP_SHADOW, NPM_SHADOWTEXT);
193 //TPATCH(TP_HILITE, NPM_HILITETEXT);
196 tmph
=PM_ItemHeight(a
, pm
);
197 tmpw
=PM_ItemWidth(a
, pm
);
204 void PM_LayoutGroup(struct PM_Window
*a
, struct PopupMenu
*pm
)
206 UWORD tw
, t
, l
, tsz
, tmp
;
210 // Is this a group? If not, return.
212 if(!(pm
->Flags
& NPM_GROUP
))
215 // Set up group offset
223 // Step 1. Calculate total weight.
224 // Hidden items and fixed size items are to be excluded from
225 // the size distribution, so they must be excluded from weight
226 // calculation aswell.
231 p
->Flags
&=~NPM_MINSIZE
;
232 if(!(p
->Flags
& NPM_HIDDEN
) && !(p
->Flags
&NPM_FIXEDSIZE
)) {
238 //kprintf("\n\nLAYOUT: Start. Maximum vertical size %ld\n", pm->Height);
240 //kprintf("LAYOUT: Initial vertical weight %ld\n", tw);
243 // Step 2. Find the items whose size is larger than what they
244 // would normally get if the available size was distributed
251 // First we have to exclude fixed size items, and items that
252 // require more space than what equal distribution would
257 if(!(p
->Flags
& NPM_HIDDEN
) && (p
->Flags
&NPM_FIXEDSIZE
|| p
->Flags
&NPM_MINSIZE
))
262 // Then we scan through the other items for those who require
263 // more space, and mark them with NPM_MINSIZE for exclusion
264 // in the loop above.
265 // If one, or more such items are found, we must repeat these
266 // steps once more, until there are no more such items left.
267 // (Until all remaining items can share the available space
271 if(!(p
->Flags
& NPM_HIDDEN
)) {
272 if(!(p
->Flags
& NPM_FIXEDSIZE
) && !(p
->Flags
& NPM_MINSIZE
)) {
277 p
->Flags
|=NPM_MINSIZE
;
278 //kprintf("LAYOUT: Removed item %s (%ld > %ld)\n", p->Title, p->Height, tmp);
281 //break; // optimization, will require less looping
290 //kprintf("LAYOUT: Remaining vertical size %ld\n", tsz);
291 //kprintf("LAYOUT: Remaining vertical weight %ld\n", tw);
294 // Step 3. Distribute the remaining size among the remaining items
295 // and position all items.
303 if(!(p
->Flags
& NPM_HIDDEN
) && !(p
->Flags
&NPM_FIXEDSIZE
) && !(p
->Flags
&NPM_MINSIZE
)) {
305 p
->Height
=tsz
/tw
; // Assign height
307 tsz
-=p
->Height
; // This will avoid leaving an empty space at the end of a group,
308 tw
--; // due to precision limitations when dividing integers.
312 p
->Left
=l
; // Set item's
313 p
->Top
=t
; // position
315 PM_LayoutGroup(a
, p
); // If this item is a group, layout will be handled here.
323 // See PML_Vertical for explanations.
328 p
->Flags
&=~NPM_MINSIZE
;
329 if(!(p
->Flags
& NPM_HIDDEN
) && !(p
->Flags
&NPM_FIXEDSIZE
)) {
341 if(!(p
->Flags
& NPM_HIDDEN
) && (p
->Flags
&NPM_FIXEDSIZE
|| p
->Flags
&NPM_MINSIZE
))
348 if(!(p
->Flags
& NPM_HIDDEN
)) {
349 if(!(p
->Flags
& NPM_FIXEDSIZE
) && !(p
->Flags
& NPM_MINSIZE
)) {
354 p
->Flags
|=NPM_MINSIZE
;
368 p
->Height
=pm
->Height
;
370 if(!(p
->Flags
& NPM_HIDDEN
) && !(p
->Flags
&NPM_FIXEDSIZE
) && !(p
->Flags
&NPM_MINSIZE
)) {
372 p
->Width
=tsz
/tw
; // Assign height
374 tsz
-=p
->Width
; // This will avoid leaving an empty space at the end of a group,
375 tw
--; // due to precision limitations when dividing integers.
379 p
->Left
=l
; // Set item's
380 p
->Top
=t
; // position
382 PM_LayoutGroup(a
, p
); // If this item is a group, layout will be handled here.
393 void PM_LayoutMenu(struct PM_Window
*a
)
395 BOOL wb
=PM_Prefs
->pmp_PulldownPos
==PMP_PD_WINDOWBAR
;
398 // Calculate Item and Group sizes
400 PM_CalcItemSize(a
, &a
->PM
);
401 a
->PM
.Width
+=a
->IconColumn
;
405 a
->PM
.Left
=PM_Prefs
->pmp_XOffset
+a
->p
->BorderWidth
;
406 a
->PM
.Top
=PM_Prefs
->pmp_YOffset
+a
->p
->BorderHeight
;
408 // Adjust for pulldowns
412 if(a
->p
->RootWnd
->BorderTop
<10) wb
=FALSE
;
418 a
->PM
.Height
=a
->p
->RootWnd
->BorderTop
- 3;
422 a
->PM
.Height
=a
->p
->RootWnd
->WScreen
->BarHeight
- 2;
428 PM_LayoutGroup(a
, &a
->PM
);
430 // Set size of window
432 a
->Height
=a
->PM
.Height
+ (PM_Prefs
->pmp_YOffset
+a
->p
->BorderHeight
)*2+1;
433 a
->Width
=a
->PM
.Width
+ (PM_Prefs
->pmp_XOffset
+a
->p
->BorderWidth
)*2+1;
435 // Adjust for pulldowns
440 a
->Height
=a
->p
->RootWnd
->BorderTop
;
444 a
->Height
=a
->p
->RootWnd
->WScreen
->BarHeight
+1;
448 a
->Width
+=2; // 2 * borderwidth
449 if(a
->Width
<a
->p
->RootWnd
->Width
-1) {
450 a
->Width
=a
->p
->RootWnd
->Width
-1;
453 a
->Width
=a
->p
->RootWnd
->WScreen
->Width
-1;