]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/PrinterSetupWizard/SecondPage.cpp
mDNSResponder-107.1.tar.gz
[apple/mdnsresponder.git] / Clients / PrinterSetupWizard / SecondPage.cpp
1 /*
2 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: SecondPage.cpp,v $
26 Revision 1.15 2005/04/13 17:46:22 shersche
27 <rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
28
29 Revision 1.14 2005/03/20 20:08:37 shersche
30 <rdar://problem/4055670> Second screen should not select a printer by default
31
32 Revision 1.13 2005/02/15 07:50:10 shersche
33 <rdar://problem/4007151> Update name
34
35 Revision 1.12 2005/02/10 22:35:11 cheshire
36 <rdar://problem/3727944> Update name
37
38 Revision 1.11 2005/01/31 23:54:30 shersche
39 <rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
40
41 Revision 1.10 2005/01/20 19:54:38 shersche
42 Fix parse error when text record is NULL
43
44 Revision 1.9 2005/01/06 08:13:50 shersche
45 Don't use moreComing flag to determine number of text record, disregard queue name if qtotal isn't defined, don't disregard queue name if "rp" is the only key specified
46
47 Revision 1.8 2005/01/04 21:09:14 shersche
48 Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
49
50 Revision 1.7 2004/12/31 07:25:27 shersche
51 Tidy up printer management, and fix memory leaks when hitting 'Cancel'
52
53 Revision 1.6 2004/12/30 01:24:02 shersche
54 <rdar://problem/3906182> Remove references to description key
55 Bug #: 3906182
56
57 Revision 1.5 2004/12/30 01:02:47 shersche
58 <rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
59 Bug #: 3734478
60
61 Revision 1.4 2004/12/29 18:53:38 shersche
62 <rdar://problem/3725106>
63 <rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
64 Bug #: 3725106, 3737413
65
66 Revision 1.3 2004/09/13 21:26:15 shersche
67 <rdar://problem/3796483> Use the moreComing flag to determine whether drawing should take place in OnAddPrinter and OnRemovePrinter callbacks
68 Bug #: 3796483
69
70 Revision 1.2 2004/06/26 03:19:57 shersche
71 clean up warning messages
72
73 Submitted by: herscher
74
75 Revision 1.1 2004/06/18 04:36:57 rpantos
76 First checked in
77
78
79 */
80
81 #include "stdafx.h"
82 #include "PrinterSetupWizardApp.h"
83 #include "PrinterSetupWizardSheet.h"
84 #include "SecondPage.h"
85 #include "DebugServices.h"
86 #include "WinServices.h"
87 #include <winspool.h>
88
89 // local variable is initialize but not referenced
90 #pragma warning(disable:4189)
91
92 // CSecondPage dialog
93
94 IMPLEMENT_DYNAMIC(CSecondPage, CPropertyPage)
95 CSecondPage::CSecondPage()
96 : CPropertyPage(CSecondPage::IDD)
97 {
98 m_psp.dwFlags &= ~(PSP_HASHELP);
99 m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
100
101 m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_BROWSE_TITLE);
102 m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE);
103
104 m_emptyListItem = NULL;
105 m_initialized = false;
106 m_waiting = false;
107 }
108
109
110 CSecondPage::~CSecondPage()
111 {
112 }
113
114
115 void
116 CSecondPage::InitBrowseList()
117 {
118 CPrinterSetupWizardSheet * psheet;
119 CString text;
120
121 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
122 require_quiet( psheet, exit );
123
124 //
125 // load the no printers message until something shows up in the browse list
126 //
127 text.LoadString(IDS_NO_PRINTERS);
128
129 LoadTextAndDisableWindow( text );
130
131 //
132 // disable the next button until there's a printer to select
133 //
134 psheet->SetWizardButtons(PSWIZB_BACK);
135
136 //
137 // disable the printer information box
138 //
139 SetPrinterInformationState( FALSE );
140 m_descriptionField.SetWindowText( L"" );
141 m_locationField.SetWindowText( L"" );
142
143 //
144 // and wait for the user to either hit the mouse or keyboard before selecting an item
145 //
146 m_gotChoice = false;
147
148 exit:
149
150 return;
151 }
152
153
154 void CSecondPage::DoDataExchange(CDataExchange* pDX)
155 {
156 CPropertyPage::DoDataExchange(pDX);
157 DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
158 DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);
159
160 DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);
161
162 DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);
163
164 DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);
165
166 DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);
167
168 }
169
170
171 afx_msg BOOL
172 CSecondPage::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message)
173 {
174 DEBUG_UNUSED(pWnd);
175 DEBUG_UNUSED(nHitTest);
176 DEBUG_UNUSED(message);
177
178 CPrinterSetupWizardSheet * psheet;
179
180 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
181 require_quiet( psheet, exit );
182
183 SetCursor(psheet->GetCursor());
184
185 exit:
186
187 return TRUE;
188 }
189
190
191 BOOL
192 CSecondPage::OnSetActive()
193 {
194 CPrinterSetupWizardSheet * psheet;
195 Printer * printer;
196 Printers::iterator it;
197 OSStatus err = kNoErr;
198 BOOL b;
199
200 b = CPropertyPage::OnSetActive();
201
202 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
203 require_action( psheet, exit, err = kUnknownErr );
204
205 // initialize the browse list...this will remove everything currently
206 // in it, and add the no printers item
207
208 InitBrowseList();
209
210 // And populate the list with any printers that we currently know about
211
212 for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ )
213 {
214 OnAddPrinter( *it, false );
215 }
216
217 printer = psheet->GetSelectedPrinter();
218
219 if ( printer != NULL )
220 {
221 m_browseList.Select( printer->item, TVGN_FIRSTVISIBLE );
222 }
223
224 exit:
225
226 return b;
227 }
228
229
230 BOOL
231 CSecondPage::OnKillActive()
232 {
233 return CPropertyPage::OnKillActive();
234 }
235
236
237 BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
238 ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
239 ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnNmClickBrowseList)
240 ON_NOTIFY(TVN_KEYDOWN, IDC_BROWSE_LIST, OnTvnKeyDownBrowseList)
241 ON_WM_SETCURSOR()
242 END_MESSAGE_MAP()
243
244
245 // Printer::EventHandler implementation
246 OSStatus
247 CSecondPage::OnAddPrinter(
248 Printer * printer,
249 bool moreComing )
250 {
251 CPrinterSetupWizardSheet * psheet;
252 OSStatus err = kNoErr;
253
254 check( IsWindow( m_hWnd ) );
255
256 m_browseList.SetRedraw(FALSE);
257
258 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
259 require_quiet( psheet, exit );
260
261 printer->item = m_browseList.InsertItem(printer->displayName);
262
263 m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
264
265 m_browseList.SortChildren(TVI_ROOT);
266
267 //
268 // if the searching item is still in the list
269 // get rid of it
270 //
271 // note that order is important here. Insert the printer
272 // item before removing the placeholder so we always have
273 // an item in the list to avoid experiencing the bug
274 // in Microsoft's implementation of CTreeCtrl
275 //
276 if (m_emptyListItem != NULL)
277 {
278 m_browseList.DeleteItem(m_emptyListItem);
279 m_emptyListItem = NULL;
280 m_browseList.EnableWindow(TRUE);
281 }
282
283 exit:
284
285 if (!moreComing)
286 {
287 m_browseList.SetRedraw(TRUE);
288 m_browseList.Invalidate();
289 }
290
291 return err;
292 }
293
294
295 OSStatus
296 CSecondPage::OnRemovePrinter(
297 Printer * printer,
298 bool moreComing)
299 {
300 CPrinterSetupWizardSheet * psheet;
301 OSStatus err = kNoErr;
302
303 check( IsWindow( m_hWnd ) );
304 check( printer );
305
306 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
307 require_quiet( psheet, exit );
308
309 m_browseList.SetRedraw(FALSE);
310
311 //
312 // check to make sure if we're the only item in the control...i.e.
313 // the list size is 1.
314 //
315 if (m_browseList.GetCount() > 1)
316 {
317 //
318 // if we're not the only thing in the list, then
319 // simply remove it from the list
320 //
321 m_browseList.DeleteItem( printer->item );
322 }
323 else
324 {
325 //
326 // if we're the only thing in the list, then redisplay
327 // it with the no printers message
328 //
329 InitBrowseList();
330 }
331
332 exit:
333
334 if ( !moreComing )
335 {
336 m_browseList.SetRedraw(TRUE);
337 m_browseList.Invalidate();
338 }
339
340 return err;
341 }
342
343
344 void
345 CSecondPage::OnResolveService( Service * service )
346 {
347 CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
348 require_quiet( psheet, exit );
349
350 check( service );
351
352 Queue * q = service->SelectedQueue();
353
354 check( q );
355
356
357 //
358 // and set it to selected
359 //
360
361 m_selectedName = service->printer->name;
362
363 //
364 // and update the printer information box
365 //
366 SetPrinterInformationState( TRUE );
367
368 m_descriptionField.SetWindowText( q->description );
369 m_locationField.SetWindowText( q->location );
370
371 //
372 // reset the cursor
373 //
374
375 SetCursor(psheet->m_active);
376
377 exit:
378
379 return;
380 }
381
382
383 void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
384 {
385 LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
386 CPrinterSetupWizardSheet * psheet;
387 Printer * printer;
388 int err = 0;
389
390 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
391 require_action( psheet, exit, err = kUnknownErr );
392
393 // The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item
394 // we selected isn't passed through correctly to this callback routine.
395
396 if ( !m_gotChoice )
397 {
398 printer = psheet->GetSelectedPrinter();
399
400 // If we really haven't selected a printer, then re-select NULL and exit
401
402 if ( !printer )
403 {
404 m_browseList.SelectItem( NULL );
405
406 goto exit;
407 }
408
409 // If we already have selected a printer, fake like we've clicked on it, but only
410 // if the CTreeCtrl hasn't already selected it
411
412 else if ( printer->item != m_browseList.GetSelectedItem() )
413 {
414 m_gotChoice = true;
415
416 m_browseList.SelectItem( printer->item );
417
418 goto exit;
419 }
420 }
421
422 HTREEITEM item = m_browseList.GetSelectedItem();
423 require_quiet( item, exit );
424
425 printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
426 require_quiet( printer, exit );
427
428 //
429 // this call will trigger a resolve. When the resolve is complete,
430 // our OnResolve will be called.
431 //
432 err = psheet->StartResolve( printer );
433 require_noerr( err, exit );
434
435 //
436 // And clear out the printer information box
437 //
438 SetPrinterInformationState( FALSE );
439 m_descriptionField.SetWindowText(L"");
440 m_locationField.SetWindowText(L"");
441
442 exit:
443
444 if (err != 0)
445 {
446 CString text;
447 CString caption;
448
449 text.LoadString(IDS_ERROR_SELECTING_PRINTER_TEXT);
450 caption.LoadString(IDS_ERROR_SELECTING_PRINTER_CAPTION);
451
452 MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
453 }
454
455 *pResult = 0;
456 }
457
458
459 void CSecondPage::OnNmClickBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
460 {
461 DEBUG_UNUSED( pNMHDR );
462
463 m_gotChoice = true;
464
465 *pResult = 0;
466 }
467
468
469 void CSecondPage::OnTvnKeyDownBrowseList( NMHDR * pNMHDR, LRESULT * pResult)
470 {
471 DEBUG_UNUSED( pNMHDR );
472
473 m_gotChoice = true;
474
475 *pResult = 0;
476 }
477
478
479 void
480 CSecondPage::LoadTextAndDisableWindow( CString & text )
481 {
482 m_emptyListItem = m_browseList.InsertItem( text, 0, 0, NULL, TVI_FIRST );
483 m_browseList.SelectItem( NULL );
484
485 //
486 // this will remove everything else in the list...we might be navigating
487 // back to this window, and the browse list might have changed since
488 // we last displayed it.
489 //
490 if ( m_emptyListItem )
491 {
492 HTREEITEM item = m_browseList.GetNextVisibleItem( m_emptyListItem );
493
494 while ( item )
495 {
496 m_browseList.DeleteItem( item );
497 item = m_browseList.GetNextVisibleItem( m_emptyListItem );
498 }
499 }
500
501 m_browseList.EnableWindow( FALSE );
502 }
503
504
505 void
506 CSecondPage::SetPrinterInformationState( BOOL state )
507 {
508 m_printerInformation.EnableWindow( state );
509
510 m_descriptionLabel.EnableWindow( state );
511
512 m_descriptionField.EnableWindow( state );
513
514 m_locationLabel.EnableWindow( state );
515
516 m_locationField.EnableWindow( state );
517
518 }
519
520
521