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