]> cygwin.com Git - cygwin-apps/setup.git/blame - proppage.cc
Use solver to check for problems and produce a list of package transactions
[cygwin-apps/setup.git] / proppage.cc
CommitLineData
df62e023 1/*
25130a4d 2 * Copyright (c) 2001, 2002, 2003 Gary R. Van Sickle.
df62e023
RC
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Gary R. Van Sickle <g.r.vansickle@worldnet.att.net>
13 *
14 */
15
16// This is the implementation of the PropertyPage class. It works closely with the
17// PropSheet class to implement a single page of the property sheet.
18
19#include "proppage.h"
20#include "propsheet.h"
21#include "win32.h"
daab12c7 22#include <shellapi.h>
b7301c43 23#include "resource.h"
f2ff9838
RC
24#include "state.h"
25
26#include "getopt++/BoolOption.h"
4d7a6eeb 27#include "Exception.h"
daab12c7 28#include "LogSingleton.h"
df62e023
RC
29
30bool PropertyPage::DoOnceForSheet = true;
31
ee91d9be
RC
32/*
33 Sizing information for some controls that are common to all pages.
34 */
35static ControlAdjuster::ControlInfo DefaultControlsInfo[] = {
a8d753b6
RC
36 {IDC_HEADICON, CP_RIGHT, CP_TOP},
37 {IDC_HEADSEPARATOR, CP_STRETCH, CP_TOP},
38 {0, CP_LEFT, CP_TOP}
ee91d9be
RC
39};
40
df62e023
RC
41PropertyPage::PropertyPage ()
42{
43 proc = NULL;
44 cmdproc = NULL;
45 IsFirst = false;
46 IsLast = false;
ee91d9be
RC
47
48 sizeProcessor.AddControlInfo (DefaultControlsInfo);
df62e023
RC
49}
50
51PropertyPage::~PropertyPage ()
52{
53}
54
55bool PropertyPage::Create (int TemplateID)
56{
57 return Create (NULL, NULL, TemplateID);
58}
59
60bool PropertyPage::Create (DLGPROC dlgproc, int TemplateID)
61{
62 return Create (dlgproc, NULL, TemplateID);
63}
64
65bool
2f3a74d1 66PropertyPage::Create (DLGPROC dlgproc,
df62e023
RC
67 BOOL (*cproc) (HWND h, int id, HWND hwndctl,
68 UINT code), int TemplateID)
69{
78b032d0 70 memset(&psp, 0, sizeof (PROPSHEETPAGE));
df62e023
RC
71 psp.dwSize = sizeof (PROPSHEETPAGE);
72 psp.dwFlags = 0;
73 psp.hInstance = GetInstance ();
74 psp.pfnDlgProc = FirstDialogProcReflector;
5039f845 75 psp.pszTemplate = MAKEINTRESOURCE(TemplateID);
df62e023
RC
76 psp.lParam = (LPARAM) this;
77 psp.pfnCallback = NULL;
78
79 proc = dlgproc;
80 cmdproc = cproc;
81
82 return true;
83}
84
e08abe3f 85INT_PTR CALLBACK
df62e023
RC
86PropertyPage::FirstDialogProcReflector (HWND hwnd, UINT message,
87 WPARAM wParam, LPARAM lParam)
88{
89 PropertyPage *This;
90
91 if (message != WM_INITDIALOG)
92 {
93 // Don't handle anything until we get a WM_INITDIALOG message, which
106d8160 94 // will have our 'this' pointer with it.
df62e023
RC
95 return FALSE;
96 }
97
98 This = (PropertyPage *) (((PROPSHEETPAGE *) lParam)->lParam);
99
e08abe3f
YS
100 SetWindowLongPtr (hwnd, DWLP_USER, (LONG_PTR) This);
101 SetWindowLongPtr (hwnd, DWLP_DLGPROC, (LONG_PTR) DialogProcReflector);
df62e023
RC
102
103 This->SetHWND (hwnd);
104 return This->DialogProc (message, wParam, lParam);
105}
106
e08abe3f 107INT_PTR CALLBACK
df62e023
RC
108PropertyPage::DialogProcReflector (HWND hwnd, UINT message, WPARAM wParam,
109 LPARAM lParam)
110{
111 PropertyPage *This;
112
e08abe3f 113 This = (PropertyPage *) GetWindowLongPtr (hwnd, DWLP_USER);
df62e023
RC
114
115 return This->DialogProc (message, wParam, lParam);
116}
117
e08abe3f 118INT_PTR CALLBACK
df62e023
RC
119PropertyPage::DialogProc (UINT message, WPARAM wParam, LPARAM lParam)
120{
4d7a6eeb
MB
121 try
122 {
123 if (proc != NULL)
df62e023
RC
124 {
125 proc (GetHWND (), message, wParam, lParam);
126 }
127
4d7a6eeb 128 switch (message)
df62e023 129 {
4d7a6eeb
MB
130 case WM_INITDIALOG:
131 {
132 OnInit ();
133
134 setTitleFont ();
135
136 // Call it here so it stores the initial client rect.
137 sizeProcessor.UpdateSize (GetHWND ());
138
139 // TRUE = Set focus to default control (in wParam).
140 return TRUE;
4d7a6eeb
MB
141 }
142 case WM_NOTIFY:
143 switch (((NMHDR FAR *) lParam)->code)
144 {
145 case PSN_APPLY:
37f49caf 146 {
e08abe3f 147 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, PSNRET_NOERROR);
37f49caf
BD
148 return TRUE;
149 }
4d7a6eeb
MB
150 case PSN_SETACTIVE:
151 {
152 if (DoOnceForSheet)
153 {
154 // Tell our parent PropSheet what its own HWND is.
155 GetOwner ()->SetHWNDFromPage (((NMHDR FAR *) lParam)->
156 hwndFrom);
157 GetOwner ()->CenterWindow ();
158 DoOnceForSheet = false;
159 }
160
161 GetOwner ()->AdjustPageSize (GetHWND ());
162
163 // Set the wizard buttons apropriately
164 if (IsFirst)
165 {
166 // Disable "Back" on first page.
167 GetOwner ()->SetButtons (PSWIZB_NEXT);
168 }
169 else if (IsLast)
170 {
171 // Disable "Next", enable "Finish" on last page
172 GetOwner ()->SetButtons (PSWIZB_BACK | PSWIZB_FINISH);
173 }
174 else
175 {
176 // Middle page, enable both "Next" and "Back" buttons
177 GetOwner ()->SetButtons (PSWIZB_BACK | PSWIZB_NEXT);
178 }
179
180 if(!wantsActivation())
181 {
e08abe3f 182 ::SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, -1);
4d7a6eeb
MB
183 return TRUE;
184 }
185
186 OnActivate ();
187
188 if (unattended_mode)
189 {
190 // -2 == disable unattended mode, display page
191 // -1 == display page but stay in unattended mode (progress bars)
19cd8e05 192 // 0 == skip to next page (in propsheet sequence)
4d7a6eeb
MB
193 // IDD_* == skip to specified page
194 long nextwindow = OnUnattended();
195 if (nextwindow == -2)
196 {
7a4e611a 197 unattended_mode = attended;
e08abe3f 198 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, 0);
4d7a6eeb
MB
199 return TRUE;
200 }
201 else if (nextwindow == -1)
202 {
e08abe3f 203 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, 0);
4d7a6eeb
MB
204 return TRUE;
205 }
206 else if (nextwindow == 0)
207 {
e08abe3f 208 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, -1);
4d7a6eeb
MB
209 return TRUE;
210 }
211 else
212 {
e08abe3f 213 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, nextwindow);
4d7a6eeb
MB
214 return TRUE;
215 }
216 }
217 else
218 {
219 // 0 == Accept activation, -1 = Don't accept
e08abe3f 220 ::SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, 0);
4d7a6eeb
MB
221 return TRUE;
222 }
223
224 }
225 break;
226 case PSN_KILLACTIVE:
37f49caf
BD
227 {
228 OnDeactivate ();
229 // FALSE = Allow deactivation
e08abe3f 230 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, FALSE);
37f49caf
BD
231 return TRUE;
232 }
4d7a6eeb
MB
233 case PSN_WIZNEXT:
234 {
235 LONG retval;
236 retval = OnNext ();
e08abe3f 237 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, retval);
4d7a6eeb
MB
238 return TRUE;
239 }
4d7a6eeb
MB
240 case PSN_WIZBACK:
241 {
242 LONG retval;
243 retval = OnBack ();
e08abe3f 244 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, retval);
4d7a6eeb
MB
245 return TRUE;
246 }
4d7a6eeb 247 case PSN_WIZFINISH:
37f49caf 248 {
c6bf266d 249 OnFinish ();
37f49caf 250 // False = Allow the wizard to finish
e08abe3f 251 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, FALSE);
37f49caf
BD
252 return TRUE;
253 }
254 case TTN_GETDISPINFO:
255 {
256 return TooltipNotificationHandler (lParam);
257 }
4d7a6eeb 258 default:
37f49caf
BD
259 {
260 // Unrecognized notification
261 return FALSE;
262 }
4d7a6eeb
MB
263 }
264 break;
265 case WM_COMMAND:
266 {
267 bool retval;
268
269 retval =
270 OnMessageCmd (LOWORD (wParam), (HWND) lParam, HIWORD (wParam));
271 if (retval == true)
272 {
273 // Handled, return 0
e08abe3f 274 SetWindowLongPtr (GetHWND (), DWLP_MSGRESULT, 0);
4d7a6eeb
MB
275 return TRUE;
276 }
277 else if (cmdproc != NULL)
278 {
4875ac88
MB
279 cmdproc (GetHWND(), LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
280 return 0;
4d7a6eeb
MB
281 }
282 break;
283 }
284 case WM_SIZE:
285 {
286 sizeProcessor.UpdateSize (GetHWND ());
287 break;
288 }
daab12c7
BD
289 case WM_CTLCOLORSTATIC:
290 {
291 // check for text controls that we've url-ified that are initializing
292 int id;
293 std::map <int, ClickableURL>::iterator theURL;
294
295 // get the ID of the control, and look it up in our list
296 if ((id = GetDlgCtrlID ((HWND)lParam)) == 0 ||
297 (theURL = urls.find (id)) == urls.end ())
298
299 // nope sorry, don't know nothing about this control
300 return FALSE;
301
302 // set FG = blue, BG = default background for a dialog
303 SetTextColor ((HDC)wParam, RGB (0, 0, 255));
304 SetBkColor ((HDC)wParam, GetSysColor (COLOR_BTNFACE));
305
306 // get the current font, add underline, and set it back
307 if (theURL->second.font == 0)
308 {
309 TEXTMETRIC tm;
310
311 GetTextMetrics ((HDC)wParam, &tm);
312 LOGFONT lf;
313 memset ((void *)&lf, 0, sizeof(LOGFONT));
314 lf.lfUnderline = TRUE;
315 lf.lfHeight = tm.tmHeight;
316 lf.lfWeight = tm.tmWeight;
317 lf.lfItalic = tm.tmItalic;
318 lf.lfStrikeOut = tm.tmStruckOut;
319 lf.lfCharSet = tm.tmCharSet;
320 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
321 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
322 lf.lfQuality = DEFAULT_QUALITY;
323 lf.lfPitchAndFamily = tm.tmPitchAndFamily;
324 GetTextFace ((HDC)wParam, LF_FACESIZE, lf.lfFaceName);
325 if ((theURL->second.font = CreateFontIndirect (&lf)) == NULL)
157dc2b8 326 Log (LOG_PLAIN) << "Warning: unable to set font for url "
daab12c7
BD
327 << theURL->second.url << endLog;
328 }
329
330 // apply the font
331 SelectObject ((HDC)wParam, theURL->second.font);
332
333 // make a brush if we have not yet
334 if (theURL->second.brush == NULL)
335 theURL->second.brush = CreateSolidBrush
336 (GetSysColor (COLOR_BTNFACE));
337
e08abe3f 338 return (INT_PTR) theURL->second.brush;
daab12c7 339 }
82306ac2
BD
340 case WM_MOUSEWHEEL:
341 // we do this so that derived classes that wish to process this message
342 // do not need to reimplement the entire WinProc, they can just
343 // provice an OnMouseWheel. (Note that mousewheel events are delivered
344 // to the parent of the window that received the scroll, so it would
345 // not work to just process this message there.)
346 return OnMouseWheel (message, wParam, lParam);
1c1913d1
RR
347
348 case WM_TIMER:
349 // similar delegation as with WM_MOUSEWHEEL
350 return OnTimerMessage (message, wParam, lParam);
351
4d7a6eeb
MB
352 default:
353 break;
df62e023
RC
354 }
355
4d7a6eeb 356 if ((message >= WM_APP) && (message < 0xC000))
df62e023
RC
357 {
358 // It's a private app message
359 return OnMessageApp (message, wParam, lParam);
360 }
4d7a6eeb 361 }
703f1a44 362 TOPLEVEL_CATCH(GetHWND (), "DialogProc");
df62e023
RC
363
364 // Wasn't handled
365 return FALSE;
366}
25130a4d 367
e08abe3f 368INT_PTR CALLBACK
82306ac2
BD
369PropertyPage::OnMouseWheel (UINT message, WPARAM wParam, LPARAM lParam)
370{
371 return 1; // not handled; define in a derived class to support this
372}
373
1c1913d1
RR
374INT_PTR CALLBACK
375PropertyPage::OnTimerMessage (UINT message, WPARAM wParam, LPARAM lParam)
376{
377 return 1; // not handled; define in a derived class to support this
378}
379
25130a4d
MB
380void
381PropertyPage::setTitleFont ()
382{
383 // These font settings will just silently fail when the resource id
384 // is not present on a page.
385 // Set header title font of each internal page
386 SetDlgItemFont(IDC_STATIC_HEADER_TITLE, "MS Shell Dlg", 8, FW_BOLD);
387 // Set the font for the IDC_STATIC_WELCOME_TITLE
388 SetDlgItemFont(IDC_STATIC_WELCOME_TITLE, "Arial", 12, FW_BOLD);
389}
daab12c7
BD
390
391std::map <int, PropertyPage::ClickableURL> PropertyPage::urls;
392
393void
08678720 394PropertyPage::makeClickable (int id, std::string link)
daab12c7
BD
395// turns a static text control in this dialog into a hyperlink
396{
397 // get the handle of the specified control
398 HWND hctl = ::GetDlgItem (GetHWND (), id);
399 if (hctl == NULL)
400 return; // invalid ID
401
402 if (urls.find (id) != urls.end ())
403 return; // already done this one
404
405 ClickableURL c;
406 c.url = link;
407 c.font = NULL; // these will be created as needed
408 c.brush = NULL;
409 if ((c.origWinProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr (hctl,
410 GWLP_WNDPROC, (LONG_PTR) & PropertyPage::urlWinProc))) == 0)
411 return; // failure
412
413 // add this to 'urls' so that the dialog and control winprocs know about it
414 urls[id] = c;
37f49caf
BD
415
416 // set a tooltip for the link
417 AddTooltip (id, link.c_str());
daab12c7
BD
418}
419
420LRESULT CALLBACK
421PropertyPage::urlWinProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
422// a winproc that we use to subclass a static text control to make a URL
423{
424 int id;
425 std::map <int, ClickableURL>::iterator theURL;
426
427 // get the ID of the control, and look it up in our list
428 if ((id = GetDlgCtrlID (hwnd)) == 0 ||
429 (theURL = urls.find (id)) == urls.end ())
430
431 // we were called for a control that we weren't installed on
432 // punt to default winproc
433 return DefWindowProc (hwnd, uMsg, wParam, lParam);
434
435 switch (uMsg)
436 {
437 case WM_LBUTTONDOWN:
438 {
439 // they clicked our URL! yay!
e08abe3f 440 intptr_t rc = (intptr_t) ShellExecute (hwnd, "open",
d2a3615c 441 theURL->second.url.c_str (), NULL, NULL, SW_SHOWNORMAL);
daab12c7
BD
442
443 if (rc <= 32)
157dc2b8 444 Log (LOG_PLAIN) << "Unable to launch browser for URL " <<
daab12c7
BD
445 theURL->second.url << " (rc = " << rc << ")" << endLog;
446 break;
447 }
448 case WM_SETCURSOR:
449 {
450 // show the hand cursor when they hover
451 // note: apparently the hand cursor isn't available
452 // on very old versions of win95? So, check return of LoadCursor
453 // and don't attempt SetCursor if it failed
454 HCURSOR c = LoadCursor (NULL, reinterpret_cast<LPCSTR>(IDC_HAND));
455 if (c)
456 SetCursor (c);
457 return TRUE;
458 }
459 case WM_NCHITTEST:
460 {
461 // normally, a static control returns HTTRANSPARENT for this
462 // which means that we would never receive the SETCURSOR message
463 return HTCLIENT;
464 }
465 case WM_DESTROY:
466 {
467 // clean up
468 WNDPROC saveWinProc = theURL->second.origWinProc;
469 DeleteObject (theURL->second.font);
470 DeleteObject (theURL->second.brush);
471 urls.erase (id);
472 return CallWindowProc (saveWinProc, hwnd, uMsg, wParam, lParam);
473 }
474 }
475
476 // pass on control to the previous winproc
477 return CallWindowProc (theURL->second.origWinProc, hwnd, uMsg, wParam, lParam);
478}
This page took 0.127662 seconds and 5 git commands to generate.