blob: 4bed3f713f7612de3e761e1b5b10ae01f014670f [file] [log] [blame]
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: SecondPage.cpp,v $
Revision 1.20 2009/06/18 18:05:50 herscher
<rdar://problem/4694554> Eliminate the first screen of Printer Wizard and maybe combine others ("I'm Feeling Lucky")
Revision 1.19 2006/08/14 23:24:09 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.18 2005/07/20 17:44:54 shersche
<rdar://problem/4124524> UI fixes for CUPS workaround
Revision 1.17 2005/07/11 20:17:15 shersche
<rdar://problem/4124524> UI fixes associated with CUPS printer workaround fix.
Revision 1.16 2005/07/07 17:53:20 shersche
Fix problems associated with the CUPS printer workaround fix.
Revision 1.15 2005/04/13 17:46:22 shersche
<rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
Revision 1.14 2005/03/20 20:08:37 shersche
<rdar://problem/4055670> Second screen should not select a printer by default
Revision 1.13 2005/02/15 07:50:10 shersche
<rdar://problem/4007151> Update name
Revision 1.12 2005/02/10 22:35:11 cheshire
<rdar://problem/3727944> Update name
Revision 1.11 2005/01/31 23:54:30 shersche
<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
Revision 1.10 2005/01/20 19:54:38 shersche
Fix parse error when text record is NULL
Revision 1.9 2005/01/06 08:13:50 shersche
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
Revision 1.8 2005/01/04 21:09:14 shersche
Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
Revision 1.7 2004/12/31 07:25:27 shersche
Tidy up printer management, and fix memory leaks when hitting 'Cancel'
Revision 1.6 2004/12/30 01:24:02 shersche
<rdar://problem/3906182> Remove references to description key
Bug #: 3906182
Revision 1.5 2004/12/30 01:02:47 shersche
<rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
Bug #: 3734478
Revision 1.4 2004/12/29 18:53:38 shersche
<rdar://problem/3725106>
<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
Bug #: 3725106, 3737413
Revision 1.3 2004/09/13 21:26:15 shersche
<rdar://problem/3796483> Use the moreComing flag to determine whether drawing should take place in OnAddPrinter and OnRemovePrinter callbacks
Bug #: 3796483
Revision 1.2 2004/06/26 03:19:57 shersche
clean up warning messages
Submitted by: herscher
Revision 1.1 2004/06/18 04:36:57 rpantos
First checked in
*/
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
#include "PrinterSetupWizardSheet.h"
#include "SecondPage.h"
#include "DebugServices.h"
#include "WinServices.h"
#include <winspool.h>
// local variable is initialize but not referenced
#pragma warning(disable:4189)
// CSecondPage dialog
IMPLEMENT_DYNAMIC(CSecondPage, CPropertyPage)
CSecondPage::CSecondPage()
: CPropertyPage(CSecondPage::IDD)
{
m_psp.dwFlags &= ~(PSP_HASHELP);
m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_BROWSE_TITLE);
m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE);
m_emptyListItem = NULL;
m_initialized = false;
m_waiting = false;
}
CSecondPage::~CSecondPage()
{
}
void
CSecondPage::InitBrowseList()
{
CPrinterSetupWizardSheet * psheet;
CString text;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
// Initialize so that nothing is selected when we add to the list
psheet->SetSelectedPrinter( NULL );
m_gotChoice = false;
m_browseList.Select( NULL, TVGN_FIRSTVISIBLE );
//
// load the no printers message until something shows up in the browse list
//
text.LoadString(IDS_NO_PRINTERS);
LoadTextAndDisableWindow( text );
//
// disable the next button until there's a printer to select
//
psheet->SetWizardButtons(PSWIZB_BACK);
//
// disable the printer information box
//
SetPrinterInformationState( FALSE );
m_descriptionField.SetWindowText( L"" );
m_locationField.SetWindowText( L"" );
exit:
return;
}
void CSecondPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);
DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);
DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);
DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);
DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);
}
afx_msg BOOL
CSecondPage::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message)
{
DEBUG_UNUSED(pWnd);
DEBUG_UNUSED(nHitTest);
DEBUG_UNUSED(message);
CPrinterSetupWizardSheet * psheet;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
SetCursor(psheet->GetCursor());
exit:
return TRUE;
}
BOOL
CSecondPage::OnSetActive()
{
CPrinterSetupWizardSheet * psheet;
Printer * printer;
Printers::iterator it;
OSStatus err = kNoErr;
BOOL b;
b = CPropertyPage::OnSetActive();
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_action( psheet, exit, err = kUnknownErr );
// Stash the selected printer if any
printer = psheet->GetSelectedPrinter();
// initialize the browse list...this will remove everything currently
// in it, and add the no printers item
InitBrowseList();
// Populate the list with any printers that we currently know about
for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ )
{
OnAddPrinter( *it, false );
}
if ( ( !printer && ( psheet->m_printers.size() > 0 ) ) || ( printer != psheet->GetSelectedPrinter() ) )
{
if ( !printer )
{
printer = psheet->m_printers.front();
}
psheet->SetSelectedPrinter( printer );
}
if ( printer )
{
m_browseList.SelectItem( printer->item );
::SetFocus( m_browseList );
}
exit:
return b;
}
BOOL
CSecondPage::OnKillActive()
{
CPrinterSetupWizardSheet * psheet;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
psheet->SetLastPage(this);
exit:
return CPropertyPage::OnKillActive();
}
BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnNmClickBrowseList)
ON_NOTIFY(TVN_KEYDOWN, IDC_BROWSE_LIST, OnTvnKeyDownBrowseList)
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
// Printer::EventHandler implementation
OSStatus
CSecondPage::OnAddPrinter(
Printer * printer,
bool moreComing )
{
CPrinterSetupWizardSheet * psheet;
Printer * selectedPrinter;
OSStatus err = kNoErr;
check( IsWindow( m_hWnd ) );
m_browseList.SetRedraw(FALSE);
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
selectedPrinter = psheet->GetSelectedPrinter();
printer->item = m_browseList.InsertItem(printer->displayName);
m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
m_browseList.SortChildren(TVI_ROOT);
//
// if the searching item is still in the list
// get rid of it
//
// note that order is important here. Insert the printer
// item before removing the placeholder so we always have
// an item in the list to avoid experiencing the bug
// in Microsoft's implementation of CTreeCtrl
//
if (m_emptyListItem != NULL)
{
m_browseList.DeleteItem(m_emptyListItem);
m_emptyListItem = NULL;
m_browseList.EnableWindow(TRUE);
}
if ( !selectedPrinter )
{
psheet->SetSelectedPrinter( printer );
m_browseList.SelectItem( printer->item );
::SetFocus( m_browseList );
}
exit:
if (!moreComing)
{
m_browseList.SetRedraw(TRUE);
m_browseList.Invalidate();
}
return err;
}
OSStatus
CSecondPage::OnRemovePrinter(
Printer * printer,
bool moreComing)
{
CPrinterSetupWizardSheet * psheet;
OSStatus err = kNoErr;
check( IsWindow( m_hWnd ) );
check( printer );
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
m_browseList.SetRedraw(FALSE);
//
// check to make sure if we're the only item in the control...i.e.
// the list size is 1.
//
if (m_browseList.GetCount() > 1)
{
//
// if we're not the only thing in the list, then
// simply remove it from the list
//
m_browseList.DeleteItem( printer->item );
}
else
{
//
// if we're the only thing in the list, then redisplay
// it with the no printers message
//
InitBrowseList();
}
exit:
if ( !moreComing )
{
m_browseList.SetRedraw(TRUE);
m_browseList.Invalidate();
}
return err;
}
void
CSecondPage::OnResolveService( Service * service )
{
CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
check( service );
Queue * q = service->SelectedQueue();
check( q );
//
// and set it to selected
//
m_selectedName = service->printer->name;
//
// and update the printer information box
//
SetPrinterInformationState( TRUE );
m_descriptionField.SetWindowText( q->description );
m_locationField.SetWindowText( q->location );
//
// reset the cursor
//
SetCursor(psheet->m_active);
exit:
return;
}
void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
CPrinterSetupWizardSheet * psheet;
Printer * printer;
int err = 0;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_action( psheet, exit, err = kUnknownErr );
// The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item
// we selected isn't passed through correctly to this callback routine.
if ( !m_gotChoice )
{
printer = psheet->GetSelectedPrinter();
// If we really haven't selected a printer, then re-select NULL and exit
if ( !printer )
{
m_browseList.SelectItem( NULL );
goto exit;
}
// If we already have selected a printer, fake like we've clicked on it, but only
// if the CTreeCtrl hasn't already selected it
else if ( printer->item != m_browseList.GetSelectedItem() )
{
m_gotChoice = true;
m_browseList.SelectItem( printer->item );
goto exit;
}
}
HTREEITEM item = m_browseList.GetSelectedItem();
require_quiet( item, exit );
printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
require_quiet( printer, exit );
//
// this call will trigger a resolve. When the resolve is complete,
// our OnResolve will be called.
//
err = psheet->StartResolve( printer );
require_noerr( err, exit );
//
// And clear out the printer information box
//
SetPrinterInformationState( FALSE );
m_descriptionField.SetWindowText(L"");
m_locationField.SetWindowText(L"");
exit:
if (err != 0)
{
CString text;
CString caption;
text.LoadString(IDS_ERROR_SELECTING_PRINTER_TEXT);
caption.LoadString(IDS_ERROR_SELECTING_PRINTER_CAPTION);
MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
}
*pResult = 0;
}
void CSecondPage::OnNmClickBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
{
DEBUG_UNUSED( pNMHDR );
m_gotChoice = true;
*pResult = 0;
}
void CSecondPage::OnTvnKeyDownBrowseList( NMHDR * pNMHDR, LRESULT * pResult)
{
DEBUG_UNUSED( pNMHDR );
m_gotChoice = true;
*pResult = 0;
}
void
CSecondPage::LoadTextAndDisableWindow( CString & text )
{
m_emptyListItem = m_browseList.InsertItem( text, 0, 0, NULL, TVI_FIRST );
m_browseList.SelectItem( NULL );
//
// this will remove everything else in the list...we might be navigating
// back to this window, and the browse list might have changed since
// we last displayed it.
//
if ( m_emptyListItem )
{
HTREEITEM item = m_browseList.GetNextVisibleItem( m_emptyListItem );
while ( item )
{
m_browseList.DeleteItem( item );
item = m_browseList.GetNextVisibleItem( m_emptyListItem );
}
}
m_browseList.EnableWindow( FALSE );
}
void
CSecondPage::SetPrinterInformationState( BOOL state )
{
m_printerInformation.EnableWindow( state );
m_descriptionLabel.EnableWindow( state );
m_descriptionField.EnableWindow( state );
m_locationLabel.EnableWindow( state );
m_locationField.EnableWindow( state );
}