AmendHub

Download

schrockwell

/

PopUp

/

PopUp.c

 

(View History)

schrockwell   Add initial PopUp library and README Latest amendment: 1 on 2025-10-15

1 #include "PopUp.h"
2
3 PopUpPtr CreatePopUp(WindowPtr window, Rect *bounds, MenuHandle menu, short style)
4 {
5 PopUpPtr popup;
6
7 popup = (PopUpPtr)NewPtr(sizeof(PopUpRec));
8 if (popup == nil)
9 return nil;
10
11 InsertMenu(menu, -1L);
12
13 popup->menu = menu;
14 popup->window = window;
15 popup->item = 1;
16 popup->bounds = *bounds;
17 popup->style = style;
18
19 return popup;
20 }
21
22 void DisposePopUp(PopUpPtr popup)
23 {
24 if (popup == nil)
25 return;
26
27 DisposPtr((Ptr)popup);
28 }
29
30 void DrawPopUp(PopUpPtr popup)
31 {
32 GrafPtr prevPort;
33
34 GetPort(&prevPort);
35 SetPort(popup->window);
36
37 // draw border
38 FrameRect(&popup->bounds);
39
40 // draw shadow
41 MoveTo(popup->bounds.left + 1, popup->bounds.bottom);
42 LineTo(popup->bounds.right, popup->bounds.bottom);
43 LineTo(popup->bounds.right, popup->bounds.top + 1);
44
45 // draw text and triangle
46 _DrawPopUpItem(popup);
47
48 SetPort(prevPort);
49 }
50
51 void _DrawPopUpItem(PopUpPtr popup)
52 {
53 Str255 menuItem;
54 Rect bgRect;
55 RgnHandle prevClip;
56
57 PolyHandle triangle;
58 Point pt1, pt2, pt3;
59
60 if (popup->style & kPopUpStyleText)
61 {
62 // determine text
63 GetItem(popup->menu, popup->item, &menuItem);
64
65 // fill bg with white
66 bgRect = popup->bounds;
67 InsetRect(&bgRect, 1, 1);
68 FillRect(&bgRect, white);
69
70 // draw item text
71 MoveTo(
72 popup->bounds.left + 5, // left margin
73 popup->bounds.bottom - 5 // bottom margin
74 );
75 TextFont(0);
76 DrawString(menuItem);
77 }
78
79 if (popup->style & kPopUpStyleCaret)
80 {
81 // draw disclosure triangle
82 pt1.h = popup->bounds.right - 17;
83 pt1.v = popup->bounds.top + 6;
84
85 pt2.h = popup->bounds.right - 5;
86 pt2.v = pt1.v;
87
88 pt3.h = popup->bounds.right - 11;
89 pt3.v = popup->bounds.top + 13;
90
91 triangle = OpenPoly();
92 MoveTo(pt1.h, pt1.v);
93 LineTo(pt2.h, pt2.v);
94 LineTo(pt3.h, pt3.v);
95 LineTo(pt1.h, pt1.v);
96 ClosePoly();
97
98 FillPoly(triangle, black);
99 KillPoly(triangle);
100 }
101 }
102
103 Boolean HandlePopUpEvent(PopUpPtr popup, EventRecord *eventPtr)
104 {
105 WindowPtr window;
106 long thePart;
107 long menuChoice;
108
109 if (eventPtr->what != mouseDown)
110 return false;
111
112 thePart = FindWindow(eventPtr->where, &window);
113
114 if (!(window == popup->window && thePart == inContent))
115 return false;
116
117 return _HandlePopUpMouseDownInContent(popup, eventPtr);
118 }
119
120 Boolean _HandlePopUpMouseDownInContent(PopUpPtr popup, EventRecord *eventPtr)
121 {
122 Point eventPoint, popUpPoint;
123 short choice;
124 Rect invertBounds;
125 GrafPtr prevPort;
126
127 eventPoint = eventPtr->where;
128 GlobalToLocal(&eventPoint);
129
130 if (PtInRect(eventPoint, &popup->bounds))
131 {
132 GetPort(&prevPort);
133 SetPort(popup->window);
134
135 invertBounds = popup->bounds;
136 InsetRect(&invertBounds, 1, 1);
137
138 popUpPoint.v = popup->bounds.top + 1;
139 popUpPoint.h = popup->bounds.left + 1;
140 LocalToGlobal(&popUpPoint);
141
142 InvertRect(&invertBounds);
143
144 if (popup->style & kPopUpStyleCheck)
145 CheckItem(popup->menu, popup->item, true);
146
147 choice = PopUpMenuSelect(
148 popup->menu,
149 popUpPoint.v,
150 popUpPoint.h,
151 popup->item
152 );
153
154 InvertRect(&invertBounds);
155
156 if (popup->style & kPopUpStyleCheck)
157 CheckItem(popup->menu, popup->item, false);
158
159 SetPort(prevPort);
160
161 if (LoWord(choice) > 0)
162 {
163 SelectPopUpItem(popup, LoWord(choice));
164 return true;
165 }
166 }
167
168 return false;
169 }
170
171 void SelectPopUpItem(PopUpPtr popup, short item)
172 {
173 GrafPtr prevPort;
174
175 GetPort(&prevPort);
176 SetPort(popup->window);
177
178 popup->item = item;
179 _DrawPopUpItem(popup);
180
181 SetPort(prevPort);
182 }