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 | } |