WindowsXP-SP1/admin/activec/conui/amcview.cpp
2020-09-30 16:53:49 +02:00

13329 lines
385 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// AMCView.cpp : implementation of the CAMCView class
//
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: amcview.cpp
//
// Contents: Base view implementation for all console views
// Also include splitter window implementation (Horizontal Splitter)
//
// History: 01-Jan-96 TRomano Created
// 16-Jul-96 WayneSc Added code to switch views and split them
//
//--------------------------------------------------------------------------
// NOTE:
// MMC starting from version 1.1 had a code which allowed to copy the view
// settings from one view to another and thus the created view would look
// the same. AMCDoc was used as temporary storage for those settings.
// But the code was NEVER used; hence was not tested and not up-to-date.
// Switching to XML persistence would require essential changes to that code,
// and at this time we cannot afford using it.
// If in the future we decide to support the feature, someone needs to look at
// MMC 1.2 sources and bring the code back. Today the code is removed from
// active sources.
// audriusz. 3/29/2000
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "AMC.h"
#include "Mainfrm.h"
#include "HtmlHelp.h"
#include "websnk.h"
#include "WebCtrl.h" // AMC Private implementation of the web view control
#include "CClvCtl.h" // List view control
#include "ocxview.h"
#include "histlist.h" // history list
#include "AMCDoc.h" // AMC Console Document
#include "AMCView.h"
#include "childfrm.h"
#include "TreeCtrl.h" // AMC Implementation of the Tree Control
#include "TaskHost.h"
#include "util.h" // GUIDFromString, GUIDToString
#include "AMCPriv.h"
#include "guidhelp.h" // ExtractObjectTypeGUID
#include "amcmsgid.h"
#include "cclvctl.h"
#include "vwtrack.h"
#include "cmenuinfo.h"
#ifdef IMPLEMENT_LIST_SAVE // See nodemgr.idl (t-dmarm)
#include "svfildlg.h" // Save File Dialog
#endif
#include "macros.h"
#include <mapi.h>
#include <mbstring.h> // for _mbslen
#include "favorite.h"
#include "favui.h"
#include "ftab.h"
#include "toolbar.h"
#include "menubtns.h" // UpdateFavorites menu.
#include "stdbar.h" // Standard toolbar.
#include "variant.h"
#include "rsltitem.h"
#include "scriptevents.h" // for IMenuItemEvents
extern "C" UINT dbg_count = 0;
enum
{
ITEM_IS_PARENT_OF_ROOT,
ITEM_NOT_IN_VIEW,
ITEM_IS_IN_VIEW,
};
enum EIndex
{
INDEX_INVALID = -1,
INDEX_BACKGROUND = -2,
INDEX_MULTISELECTION = -3,
INDEX_OCXPANE = -4,
INDEX_WEBPANE = -5,
};
enum ScopeFolderItems
{
SFI_TREE_TAB = 1,
SFI_FAVORITES_TAB = 2
};
const UINT CAMCView::m_nShowWebContextMenuMsg = ::RegisterWindowMessage (_T("CAMCView::ShowWebContextMenu"));
const UINT CAMCView::m_nProcessMultiSelectionChangesMsg = ::RegisterWindowMessage (_T("CAMCView::OnProcessMultiSelectionChanges"));
const UINT CAMCView::m_nAddPageBreakAndNavigateMsg = ::RegisterWindowMessage (_T("CAMCView::AddPageBreakAndNavigate"));
const UINT CAMCView::m_nJiggleListViewFocusMsg = ::RegisterWindowMessage (_T("CAMCView::JiggleListViewFocus"));
const UINT CAMCView::m_nDeferRecalcLayoutMsg = ::RegisterWindowMessage (_T("CAMCView::DeferRecalcLayout"));
void CALLBACK TrackerCallback(TRACKER_INFO& info, bool bAcceptChange, bool bSyncLayout);
void GetFullPath(CAMCTreeView &ctc, HTREEITEM hti, CString &strPath);
BOOL PtInWindow(CWnd* pWnd, CPoint pt);
#ifdef DBG
CTraceTag tagLayout (_T("CAMCView"), _T("Layout"));
CTraceTag tagSplitterTracking (_T("CAMCView"), _T("Splitter tracking"));
CTraceTag tagListSelection (_T("Result list"), _T("Selection"));
CTraceTag tagViewActivation (_T("View Activation"), _T("View Activation"));
#endif
/*+-------------------------------------------------------------------------*
* CAMCView::ScNotifySelect
*
*
*--------------------------------------------------------------------------*/
SC CAMCView::ScNotifySelect (
INodeCallback* pCallback,
HNODE hNode,
bool fMultiSelect,
bool fSelect,
SELECTIONINFO* pSelInfo)
{
DECLARE_SC(sc, TEXT("CAMCView::ScNotifySelect"));
// parameter check
sc = ScCheckPointers(pCallback);
if (sc)
return sc;
// pSelInfo can be NULL only for multi-select.
if (!pSelInfo && !fMultiSelect)
return (sc = E_INVALIDARG);
#ifdef DBG
Trace (tagListSelection, _T("%s (fSelect=%s, pwnd=0x%08x)"),
(fMultiSelect) ? _T("NCLBK_MULTI_SELECT") : _T("NCLBK_SELECT"),
(fSelect) ? _T("true") : _T("false"),
static_cast<CWnd *>(this));
#endif
// we want this error (not a failure to broadcast the event) to be returned,
// so cache it and assign before return
SC sc_notify = (pCallback->Notify (hNode, fMultiSelect ? NCLBK_MULTI_SELECT :NCLBK_SELECT,
fSelect, reinterpret_cast<LPARAM>(pSelInfo)));
// fire event whenever the selection changes, but not if
// its a background hit or loss of focus
if(fMultiSelect ||
(pSelInfo->m_bBackground == FALSE && (fSelect == TRUE || pSelInfo->m_bDueToFocusChange == FALSE)))
{
sc = ScFireEvent(CAMCViewObserver::ScOnResultSelectionChange, this);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
sc = sc_notify;
return sc;
}
/*+-------------------------------------------------------------------------*
* GetAMCView
*
* Returns the CAMCView window for any child of CChildFrame.
*--------------------------------------------------------------------------*/
CAMCView* GetAMCView (CWnd* pwnd)
{
/*
* get the input window's parent frame window
*/
CWnd* pFrame = pwnd->GetParentFrame();
/*
* if we couldn't find a parent frame, or that parent frame isn't
* of type CChildFrame, fail
*/
if ((pFrame == NULL) || !pFrame->IsKindOf (RUNTIME_CLASS (CChildFrame)))
return (NULL);
/*
* get the first view of the frame window
*/
CWnd* pView = pFrame->GetDlgItem (AFX_IDW_PANE_FIRST);
/*
* if we can't find a window with the right ID, or the one we find
* isn't of type CAMCView, fail
*/
if ((pView == NULL) || !pView->IsKindOf (RUNTIME_CLASS (CAMCView)))
return (NULL);
return (dynamic_cast<CAMCView*>(pView));
}
//############################################################################
//############################################################################
//
// Implementation of class CMMCView
//
//############################################################################
//############################################################################
/*+-------------------------------------------------------------------------*
* class CMMCView
*
*
* PURPOSE: The COM 0bject that exposes the View interface.
*
*+-------------------------------------------------------------------------*/
class CMMCView :
public CTiedComObject<CAMCView>,
public CMMCIDispatchImpl<View>
{
typedef CAMCView CMyTiedObject;
public:
BEGIN_MMC_COM_MAP(CMMCView)
END_MMC_COM_MAP()
public:
//#######################################################################
//#######################################################################
//
// Item and item collection related methods
//
//#######################################################################
//#######################################################################
MMC_METHOD1(get_ActiveScopeNode, PPNODE);
MMC_METHOD1(put_ActiveScopeNode, PNODE);
MMC_METHOD1(get_Selection, PPNODES);
MMC_METHOD1(get_ListItems, PPNODES);
MMC_METHOD2(SnapinScopeObject, VARIANT, PPDISPATCH);
MMC_METHOD1(SnapinSelectionObject, PPDISPATCH);
//#######################################################################
//#######################################################################
MMC_METHOD2(Is, PVIEW, VARIANT_BOOL *);
MMC_METHOD1(get_Document, PPDOCUMENT);
//#######################################################################
//#######################################################################
//
// Selection changing methods
//
//#######################################################################
//#######################################################################
MMC_METHOD0(SelectAll);
MMC_METHOD1(Select, PNODE);
MMC_METHOD1(Deselect, PNODE);
MMC_METHOD2(IsSelected, PNODE, PBOOL);
//#######################################################################
//#######################################################################
//
// Verb and selection related methods
//
//#######################################################################
//#######################################################################
MMC_METHOD1(DisplayScopeNodePropertySheet, VARIANT);
MMC_METHOD0(DisplaySelectionPropertySheet);
MMC_METHOD1(CopyScopeNode, VARIANT);
MMC_METHOD0(CopySelection);
MMC_METHOD1(DeleteScopeNode, VARIANT);
MMC_METHOD0(DeleteSelection);
MMC_METHOD2(RenameScopeNode, BSTR, VARIANT);
MMC_METHOD1(RenameSelectedItem, BSTR);
MMC_METHOD2(get_ScopeNodeContextMenu,VARIANT, PPCONTEXTMENU);
MMC_METHOD1(get_SelectionContextMenu,PPCONTEXTMENU);
MMC_METHOD1(RefreshScopeNode, VARIANT);
MMC_METHOD0(RefreshSelection);
MMC_METHOD1(ExecuteSelectionMenuItem, BSTR /*MenuItemPath*/);
MMC_METHOD2(ExecuteScopeNodeMenuItem, BSTR /*MenuItemPath*/, VARIANT /*varScopeNode = ActiveScopeNode */);
MMC_METHOD4(ExecuteShellCommand, BSTR /*Command*/, BSTR /*Directory*/, BSTR /*Parameters*/, BSTR /*WindowState*/);
//#######################################################################
//#######################################################################
//
// Frame and view related methods
//
//#######################################################################
//#######################################################################
MMC_METHOD1(get_Frame, PPFRAME);
MMC_METHOD0(Close);
MMC_METHOD1(get_ScopeTreeVisible, PBOOL);
MMC_METHOD1(put_ScopeTreeVisible, BOOL);
MMC_METHOD0(Back);
MMC_METHOD0(Forward);
MMC_METHOD1(put_StatusBarText, BSTR);
MMC_METHOD1(get_Memento, PBSTR);
MMC_METHOD1(ViewMemento, BSTR);
//#######################################################################
//#######################################################################
//
// List related methods
//
//#######################################################################
//#######################################################################
MMC_METHOD1(get_Columns, PPCOLUMNS);
MMC_METHOD3(get_CellContents, PNODE, long, PBSTR);
MMC_METHOD2(ExportList, BSTR, ExportListOptions);
MMC_METHOD1(get_ListViewMode, PLISTVIEWMODE);
MMC_METHOD1(put_ListViewMode, ListViewMode);
//#######################################################################
//#######################################################################
//
// ActiveX control related methods
//
//#######################################################################
//#######################################################################
MMC_METHOD1(get_ControlObject, PPDISPATCH);
};
/*
* WM_APPCOMMAND is only defined in winuser.h if _WIN32_WINNT >= 0x0500.
* We need these definitions, but can't use _WIN32_WINNT==0x0500 (yet).
*/
#ifndef WM_APPCOMMAND
#define WM_APPCOMMAND 0x0319
#define APPCOMMAND_BROWSER_BACKWARD 1
#define APPCOMMAND_BROWSER_FORWARD 2
#define APPCOMMAND_BROWSER_REFRESH 3
#define FAPPCOMMAND_MOUSE 0x8000
#define FAPPCOMMAND_KEY 0
#define FAPPCOMMAND_OEM 0x1000
#define FAPPCOMMAND_MASK 0xF000
#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
#endif // WM_APPCOMMAND
//############################################################################
//############################################################################
//
// Implementation of class CAMCView
//
//############################################################################
//############################################################################
IMPLEMENT_DYNCREATE(CAMCView, CView);
BEGIN_MESSAGE_MAP(CAMCView, CView)
//{{AFX_MSG_MAP(CAMCView)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_CREATE()
ON_WM_SETFOCUS()
ON_WM_CONTEXTMENU()
ON_WM_DESTROY()
ON_UPDATE_COMMAND_UI(ID_FILE_SNAPINMANAGER, OnUpdateFileSnapinmanager)
ON_WM_SHOWWINDOW()
ON_COMMAND(ID_MMC_NEXT_PANE, OnNextPane)
ON_COMMAND(ID_MMC_PREV_PANE, OnPrevPane)
ON_WM_SETCURSOR()
ON_COMMAND(ID_MMC_CONTEXTHELP, OnContextHelp)
ON_COMMAND(ID_HELP_SNAPINHELP, OnSnapInHelp)
ON_COMMAND(ID_SNAPIN_ABOUT, OnSnapinAbout)
ON_COMMAND(ID_HELP_HELPTOPICS, OnHelpTopics)
ON_WM_SIZE()
ON_WM_SYSKEYDOWN()
ON_WM_PALETTECHANGED()
ON_WM_QUERYNEWPALETTE()
ON_WM_SYSCOLORCHANGE()
ON_WM_DRAWCLIPBOARD()
ON_WM_SETTINGCHANGE()
ON_WM_MENUSELECT()
//}}AFX_MSG_MAP
// keep this outside the AFX_MSG_MAP markers so ClassWizard doesn't munge it
ON_COMMAND_RANGE(ID_MMC_CUT, ID_MMC_PRINT, OnVerbAccelKey)
// WARNING: If your message handler has void return use ON_MESSAGE_VOID !!
ON_MESSAGE(MMC_MSG_CONNECT_TO_CIC, OnConnectToCIC)
ON_MESSAGE(MMC_MSG_CONNECT_TO_TPLV, OnConnectToTPLV)
ON_MESSAGE(MMC_MSG_GET_ICON_INFO, OnGetIconInfoForSelectedNode)
ON_MESSAGE(WM_APPCOMMAND, OnAppCommand)
ON_REGISTERED_MESSAGE (m_nShowWebContextMenuMsg, OnShowWebContextMenu)
ON_REGISTERED_MESSAGE (m_nProcessMultiSelectionChangesMsg, OnProcessMultiSelectionChanges)
ON_REGISTERED_MESSAGE (m_nAddPageBreakAndNavigateMsg, OnAddPageBreakAndNavigate)
ON_REGISTERED_MESSAGE (m_nJiggleListViewFocusMsg, OnJiggleListViewFocus)
ON_REGISTERED_MESSAGE (m_nDeferRecalcLayoutMsg, OnDeferRecalcLayout)
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
ON_NOTIFY(FTN_TABCHANGED, IDC_ResultTabCtrl, OnChangedResultTab)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAMCView construction/destruction
const CSize CAMCView::m_sizEdge (GetSystemMetrics (SM_CXEDGE),
GetSystemMetrics (SM_CYEDGE));
const int CAMCView::m_cxSplitter = 3;
//+-------------------------------------------------------------------
//
// Member: CAMCView::OnMenuSelect
//
// Synopsis: Handles WM_MENUSELECT for Favorites menu.
//
// Arguments: [nItemID] - the resource id of menu item.
// [nFlags] - MF_* flags
//
// Returns: none
//
//--------------------------------------------------------------------
void CAMCView::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
DECLARE_SC(sc, TEXT("CAMCView::OnMenuSelect"));
CMainFrame* pFrame = AMCGetMainWnd();
sc = ScCheckPointers(pFrame, E_UNEXPECTED);
if (sc)
return;
// Pass onto the mainframe.
return pFrame->OnMenuSelect(nItemID, nFlags, hSysMenu);
}
CAMCView::CAMCView() :
m_pResultFolderTabView(new CFolderTabView(this)) // dynamically allocated for decoupling
{
TRACE_CONSTRUCTOR(CAMCView);
// Init pointer members to NULL
m_nViewID = 0;
m_pTreeCtrl = NULL;
m_pListCtrl = NULL;
m_pWebViewCtrl = NULL;
m_pViewExtensionCtrl = NULL;
m_pOCXHostView = NULL;
m_nSelectNestLevel = 0;
// if the view is a listview, then this member define what the view
// mode is for all snapins with that view.
m_nViewMode = LVS_REPORT; // REVIEW: Must we persist this - ravi
// REVIEW consider moving the above initialzation to the InitSplitter
// CommonConstruct
// NOTE moved code from InitSplitter into the contructor and deleted InitSplitter
// Default values for view. User can set these values with SetPaneInfo;
m_PaneInfo[ePane_ScopeTree].pView = NULL;
m_PaneInfo[ePane_ScopeTree].cx = -1;
m_PaneInfo[ePane_ScopeTree].cxMin = 50;
m_PaneInfo[ePane_Results].pView = NULL;
m_PaneInfo[ePane_Results].cx = -1;
m_PaneInfo[ePane_Results].cxMin = 50;
m_pTracker = NULL;
m_rectResultFrame = g_rectEmpty;
m_rectVSplitter = g_rectEmpty;
// m_fDontPersistOCX = FALSE;
// root node for the view
m_hMTNode = 0;
// Bug 157408: remove the "Type" column for static nodes
// m_columnWidth[0] = 90;
// m_columnWidth[1] = 50;
m_columnWidth[0] = 200;
m_columnWidth[1] = 0;
m_iFocusedLV = -1;
m_bLVItemSelected = FALSE;
m_DefaultLVStyle = 0;
m_bProcessMultiSelectionChanges = false;
m_htiCut = NULL;
m_nReleaseViews = 0;
m_htiStartingSelectedNode = NULL;
m_bLastSelWasMultiSel = false;
m_eCurrentActivePane = eActivePaneNone;
m_fRootedAtNonPersistedDynamicNode = false;
m_fSnapinDisplayedHelp = false;
m_fActivatingSpecialResultPane = false;
m_bDirty = false;
m_fViewExtended = false;
m_pHistoryList = new CHistoryList (this);
m_ListPadNode = NULL;
/*
* Bug 103604: Mark this as an author mode view if it was created in
* author mode. If we're loading a user mode console file, it will
* have author mode views and possibly some views that were created
* in user mode, but this code will mark all of the views as non-author
* mode views. CAMCView::Persist will fix that.
*/
CAMCApp* pApp = AMCGetApp();
if (pApp != NULL)
m_bAuthorModeView = (pApp->GetMode() == eMode_Author);
else
m_bAuthorModeView = true;
}
CAMCView::~CAMCView()
{
TRACE_DESTRUCTOR(CAMCView);
// Delete all pointer members. (C++ checks to see if they are NULL before deleting)
// The standard ~CWnd destructor will call DestroyWindow()
// REVIEW set the pointers to NULL after deleting them
// Note Done
// CViews "delete this" in PostNcDestroy, no need to delete here
//delete m_pTreeCtrl;
m_pTreeCtrl = NULL;
m_pListCtrl->Release();
m_pListCtrl = NULL;
/*
* DONT_DELETE_VIEWS
*
* CViews "delete this" in PostNcDestroy, no need to delete
* here if the web view control is derived from CView. See
* AttachWebViewAsResultPane (search for "DONT_DELETE_VIEWS")
* for the ASSERTs that make sure this code is right.
*/
//delete m_pWebViewCtrl;
//m_pWebViewCtrl = NULL;
/*
* CViews "delete this" in PostNcDestroy, no need to delete here
*/
m_pOCXHostView = NULL;
m_pResultFolderTabView = NULL;
if (m_ViewData.m_spNodeManager != NULL)
m_ViewData.m_spNodeManager->CleanupViewData(
reinterpret_cast<LONG_PTR>(&m_ViewData));
ASSERT (m_ViewData.m_pMultiSelection == NULL);
delete m_pHistoryList;
// First destroy the IControlbarsCache as snapins call CAMCViewToolbars
// to cleanup toolbars before the CAMCViewToolbars itself gets destroyed.
m_ViewData.m_spControlbarsCache = NULL;
// (UI cleanup) release toolbars related to this view.
m_spAMCViewToolbars = std::auto_ptr<CAMCViewToolbars>(NULL);
m_spStandardToolbar = std::auto_ptr<CStandardToolbar>(NULL);
//m_spStandardToolbar = NULL;
//m_spAMCViewToolbars = NULL;
}
//############################################################################
//############################################################################
//
// CAMCView: Object model methods - View Interface
//
//############################################################################
//############################################################################
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetOptionalScopeNodeParameter
*
* PURPOSE: Helper function - returns the scope node pointer, if supplied
* in the variant, or the Active Scope node pointer, if not
* supplied.
*
* PARAMETERS:
* VARIANT varScopeNode : The parameter, which can be empty. NOTE: This is a
* reference, so we don't need to call VariantClear on it.
* PPNODE ppNode :
* bool& bMatchedGivenNode: If true the returned ppNode corresponds to the given node
* applies only if given node is in bookmark format.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScGetOptionalScopeNodeParameter(VARIANT &varScopeNode, PPNODE ppNode, bool& bMatchedGivenNode)
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetOptionalScopeNodeParameter"));
sc = ScCheckPointers(ppNode);
if(sc)
return sc;
// init the out parameter
*ppNode = NULL;
bMatchedGivenNode = true;
// supply the optional parameter if it is missing
if(IsOptionalParamMissing(varScopeNode))
{
sc = Scget_ActiveScopeNode(ppNode);
return sc;
}
VARIANT* pvarTemp = ConvertByRefVariantToByValue(&varScopeNode);
sc = ScCheckPointers(pvarTemp,E_UNEXPECTED);
if(sc)
return sc;
bool bByReference = ( VT_BYREF == (V_VT(pvarTemp) & VT_BYREF) ); // value passed by reference
UINT uiVarType = (V_VT(pvarTemp) & VT_TYPEMASK); // get variable type (strip flags)
if(uiVarType == VT_DISPATCH) // do we have a dispatch interface.
{
IDispatchPtr spDispatch = NULL;
if(bByReference) // a reference, use ppDispVal
spDispatch = *(pvarTemp->ppdispVal);
else
spDispatch = pvarTemp->pdispVal; // passed by value, use pDispVal
sc = ScCheckPointers(spDispatch.GetInterfacePtr());
if(sc)
return sc;
// at this point spDispatch is correctly set. QI for Node from it.
NodePtr spNode = spDispatch;
if(spNode == NULL)
return (sc = E_INVALIDARG);
*ppNode = spNode.Detach(); // keep the reference.
}
else if(uiVarType == VT_BSTR)
{
// Name: get string properly ( see if it's a reference )
LPOLESTR lpstrBookmark = bByReference ? *(pvarTemp->pbstrVal) : pvarTemp->bstrVal;
// get the bookmark
CBookmark bm;
sc = bm.ScLoadFromString(lpstrBookmark);
if(sc)
return sc;
if(!bm.IsValid())
return (sc = E_UNEXPECTED);
IScopeTree* const pScopeTree = GetScopeTreePtr();
sc = ScCheckPointers(pScopeTree, E_UNEXPECTED);
if(sc)
return sc;
NodePtr spNode;
// Need a bool variable to find if exact match is found or not, cannot return
// MMC specific error codes from nodemgr to conui.
bMatchedGivenNode = false;
sc = pScopeTree->GetNodeFromBookmark( bm, this, ppNode, bMatchedGivenNode);
if(sc)
return sc;
}
else
return (sc = E_INVALIDARG);
// we should have a valid node at this point.
if(!ppNode)
return (sc = E_UNEXPECTED);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_ActiveScopeNode
*
* PURPOSE: Implements get method for Wiew.ActiveScopeNode property
*
* PARAMETERS:
* PPNODE ppNode - resulting node
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scget_ActiveScopeNode( PPNODE ppNode)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_ActiveScopeNode"));
// checking parameters
sc= ScCheckPointers(ppNode);
if (sc)
return sc;
// get selected node
HNODE hNode = GetSelectedNode();
sc= ScCheckPointers((LPVOID)hNode, E_FAIL);
if (sc)
return sc;
// get node callback
INodeCallback* pNodeCallBack = GetNodeCallback();
sc= ScCheckPointers(pNodeCallBack, E_FAIL);
if (sc)
return sc;
// now get an HMTNODE
HMTNODE hmtNode = NULL;
sc = pNodeCallBack->GetMTNode(hNode, &hmtNode);
if (sc)
return sc;
// geting pointer to scope tree
IScopeTree* const pScopeTree = GetScopeTreePtr();
sc= ScCheckPointers(pScopeTree, E_UNEXPECTED);
if (sc)
return sc;
// map to PNODE
sc = pScopeTree->GetMMCNode(hmtNode, ppNode);
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* METHOD: CExpandSyncModeLock
*
* PURPOSE: constructing the object of this class locks MMC in syncronous
* expansion mode (node expansion will send MMCN_EXPANDSYNC to snapin)
* destructor of the class restores the previous mode
*
\***************************************************************************/
class CExpandSyncModeLock
{
IScopeTreePtr m_spScopeTree;
bool m_fSyncExpandWasRequired;
public:
CExpandSyncModeLock( IScopeTree *pScopeTree ) : m_spScopeTree(pScopeTree),
m_fSyncExpandWasRequired(false)
{
ASSERT( m_spScopeTree != NULL );
if ( m_spScopeTree )
{
m_fSyncExpandWasRequired = (m_spScopeTree->IsSynchronousExpansionRequired() == S_OK);
m_spScopeTree->RequireSynchronousExpansion (true);
}
}
~CExpandSyncModeLock()
{
if ( m_spScopeTree )
{
m_spScopeTree->RequireSynchronousExpansion ( m_fSyncExpandWasRequired );
}
}
};
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scset_ActiveScopeNode
*
* PURPOSE: Implements set method for Wiew.ActiveScopeNode property
*
* PARAMETERS:
* PNODE pNode - node to activate
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scput_ActiveScopeNode( PNODE pNode)
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_ActiveScopeNode"));
// checking parameters
sc= ScCheckPointers(pNode);
if (sc)
return sc;
// geting pointer to scope tree
IScopeTree* const pScopeTree = GetScopeTreePtr();
sc= ScCheckPointers(pScopeTree, E_UNEXPECTED);
if (sc)
return sc;
// Converting PNODE to TNODEID
MTNODEID ID = 0;
sc = pScopeTree->GetNodeID(pNode, &ID);
if (sc)
return sc;
// always require syncronous expansion for Object Model
// see bug #154694
CExpandSyncModeLock lock( pScopeTree );
// selecting the node
sc = ScSelectNode(ID);
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::Scget_Selection
*
* PURPOSE: creates enumerator for Selected Nodes
*
* PARAMETERS:
* PPNODES ppNodes - resulting enumerator
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::Scget_Selection( PPNODES ppNodes )
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_SelectedItems"));
// check for list view control
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// get enumerator from list control
sc = m_pListCtrl->Scget_SelectedItems(ppNodes);
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::Scget_ListItems
*
* PURPOSE:
*
* PARAMETERS:
* PPNODES ppNodes - resulting enumerator
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::Scget_ListItems( PPNODES ppNodes )
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_ListItems"));
// check for list view control
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// get enumerator from list control
sc = m_pListCtrl->Scget_ListItems(ppNodes);
if (sc)
return sc;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScSnapinScopeObject
//
// Synopsis: Get the IDispatch* from snapin for given ScopeNode object.
//
// Arguments: varScopeNode - Given ScopeNode object.
// ScopeNodeObject [out] - IDispatch for ScopeNode object.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScSnapinScopeObject (VARIANT& varScopeNode, /*[out]*/PPDISPATCH ScopeNodeObject)
{
DECLARE_SC(sc, _T("CAMCView::ScSnapinScopeObject"));
sc = ScCheckPointers(ScopeNodeObject);
if (sc)
return sc;
*ScopeNodeObject = NULL;
bool bMatchedGivenNode = false; // unused
NodePtr spNode = NULL;
sc = ScGetOptionalScopeNodeParameter(varScopeNode, &spNode, bMatchedGivenNode);
if(sc)
return sc;
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(spNode.GetInterfacePtr(), pNC, E_UNEXPECTED);
if(sc)
return sc;
sc = pNC->QueryCompDataDispatch(spNode, ScopeNodeObject);
if (sc)
return sc;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScSnapinSelectionObject
//
// Synopsis: Get the IDispatch* from snapin for selected items in result pane.
//
// Arguments: SelectedObject [out] - IDispatch for Selected items object.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScSnapinSelectionObject (PPDISPATCH SelectedObject)
{
DECLARE_SC(sc, _T("CAMCView::ScSnapinSelectionObject"));
sc = ScCheckPointers(SelectedObject);
if (sc)
return sc;
*SelectedObject = NULL;
if (!HasList()) // not a list. Return error
return (sc = ScFromMMC(MMC_E_NOLIST));
LPARAM lvData = LVDATA_ERROR;
sc = ScGetSelectedLVItem(lvData);
if (sc)
return sc;
HNODE hNode = GetSelectedNode();
sc = ScCheckPointers(hNode, E_UNEXPECTED);
if (sc)
return sc;
INodeCallback* pNodeCallback = GetNodeCallback();
sc = ScCheckPointers(pNodeCallback, E_UNEXPECTED);
if(sc)
return sc.ToHr();
sc = pNodeCallback->QueryComponentDispatch(hNode, lvData, SelectedObject);
if (sc)
return sc;
return (sc);
}
/***************************************************************************\
*
* METHOD: CAMCView::ScIs
*
* PURPOSE: compares two views if they are the same
*
* PARAMETERS:
* PVIEW pView - [in] another view
* VARIANT_BOOL * pbTheSame - [out] comparison result
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::ScIs (PVIEW pView, VARIANT_BOOL *pbTheSame)
{
DECLARE_SC(sc, TEXT("CAMCView::ScIs"));
// parameter check
sc = ScCheckPointers(pView, pbTheSame);
if (sc)
return sc;
*pbTheSame = CComPtr<View>(pView).IsEqualObject(m_spView)
? VARIANT_TRUE : VARIANT_FALSE;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScSelectAll
//
// Synopsis: Selects all items in the result pane
//
// Arguments: None
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScSelectAll ()
{
DECLARE_SC(sc, _T("CAMCView::ScSelectAll"));
if (! (GetListOptions() & RVTI_LIST_OPTIONS_MULTISELECT) )
return (sc = ScFromMMC(MMC_E_NO_MULTISELECT));
// check for list view control
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// forward to list control
sc = m_pListCtrl->ScSelectAll();
if (sc)
return sc;
return (sc);
}
/***************************************************************************\
*
* METHOD: CAMCView::ScSelect
*
* PURPOSE: selects item identified by node [implements View.Select()]
*
* PARAMETERS:
* PNODE pNode - node to select
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::ScSelect( PNODE pNode )
{
DECLARE_SC(sc, TEXT("CAMCView::ScSelect"));
// parameter check
sc = ScCheckPointers(pNode);
if (sc)
return sc;
// check for list view control
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// forward to list control
sc = m_pListCtrl->ScSelect( pNode );
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::ScDeselect
*
* PURPOSE: deselects item identified by node [implements View.Deselect()]
*
* PARAMETERS:
* PNODE pNode - node to deselect
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::ScDeselect( PNODE pNode)
{
DECLARE_SC(sc, TEXT("CAMCView::ScDeselect"));
// parameter check
sc = ScCheckPointers(pNode);
if (sc)
return sc;
// check for list view control
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// forward to list control
sc = m_pListCtrl->ScDeselect( pNode );
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::ScIsSelected
*
* PURPOSE: checks the status of item identified by node [implements View.IsSelected]
*
* PARAMETERS:
* PNODE pNode - node to examine
* PBOOL pIsSelected - storage for result
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::ScIsSelected( PNODE pNode, PBOOL pIsSelected )
{
DECLARE_SC(sc, TEXT("CAMCView::ScIsSelected"));
// parameter check
sc = ScCheckPointers(pNode, pIsSelected);
if (sc)
return sc;
*pIsSelected = FALSE;
// check for list view control
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// forward to list control
sc = m_pListCtrl->ScIsSelected( pNode, pIsSelected );
if (sc)
return sc;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScExecuteScopeItemVerb
//
// Synopsis: Get the context and pass it on to nodemgr to execute
// given verb.
//
// Arguments: [verb] - Verb to execute
// [varScopeNode] - Optional scope node (if not given,
// currently selected item will be used.)
// [bstrNewName] - valid for Rename else NULL.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScExecuteScopeItemVerb (MMC_CONSOLE_VERB verb, VARIANT& varScopeNode, BSTR bstrNewName)
{
DECLARE_SC(sc, _T("CAMCView::ScExecuteScopeItemVerb"));
NodePtr spNode = NULL;
bool bMatchedGivenNode = false;
// We should navigate to exact node to execute the verb.
sc = ScGetOptionalScopeNodeParameter(varScopeNode, &spNode, bMatchedGivenNode);
if(sc)
return sc;
if (! bMatchedGivenNode)
return (sc = ScFromMMC(IDS_ACTION_COULD_NOTBE_COMPLETED));
HNODE hNode = NULL;
sc = ScGetHNodeFromPNode(spNode, hNode);
if (sc)
return sc;
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(spNode.GetInterfacePtr(), pNC);
if(sc)
return sc;
sc = pNC->ExecuteScopeItemVerb(verb, hNode, bstrNewName);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScExecuteResultItemVerb
//
// Synopsis: Get the currently selected context and pass it on to
// nodemgr to execute given verb.
//
// Arguments: [verb] - Verb to execute
// [bstrNewName] - valid for Rename else NULL.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScExecuteResultItemVerb (MMC_CONSOLE_VERB verb, BSTR bstrNewName)
{
DECLARE_SC(sc, _T("CAMCView::ScExecuteResultItemVerb"));
if (!HasList()) // not a list. Return error
return (sc = ScFromMMC(MMC_E_NOLIST));
LPARAM lvData = LVDATA_ERROR;
sc = ScGetSelectedLVItem(lvData);
if (sc)
return sc;
if (lvData == LVDATA_ERROR)
return (sc = E_UNEXPECTED);
HNODE hNode = GetSelectedNode();
sc = ScCheckPointers(hNode, E_UNEXPECTED);
if (sc)
return sc;
INodeCallback* pNodeCallback = GetNodeCallback();
sc = ScCheckPointers(pNodeCallback, E_UNEXPECTED);
if(sc)
return sc.ToHr();
sc = pNodeCallback->ExecuteResultItemVerb( verb, hNode, lvData, bstrNewName);
if (sc)
return sc;
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScDisplayScopeNodePropertySheet
*
* PURPOSE: Displays the property sheet for a scope node.
*
* PARAMETERS:
* VARIANT varScopeNode :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScDisplayScopeNodePropertySheet(VARIANT& varScopeNode)
{
DECLARE_SC(sc, TEXT("CAMCView::ScDisplayPropertySheet"));
sc = ScExecuteScopeItemVerb(MMC_VERB_PROPERTIES, varScopeNode, NULL);
if (sc)
return sc;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScDisplaySelectionPropertySheet
//
// Synopsis: Show the property sheet for selected result item(s).
//
// Arguments: None
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScDisplaySelectionPropertySheet ()
{
DECLARE_SC(sc, _T("CAMCView::ScDisplaySelectionPropertySheet"));
sc = ScExecuteResultItemVerb(MMC_VERB_PROPERTIES, NULL);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScCopyScopeNode
//
// Synopsis: Copy the specified scope node (if given) or currently
// selected node to clipboard.
//
// Arguments: [varScopeNode] - given node.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScCopyScopeNode (VARIANT& varScopeNode)
{
DECLARE_SC(sc, _T("CAMCView::ScCopyScopeNode"));
sc = ScExecuteScopeItemVerb(MMC_VERB_COPY, varScopeNode, NULL);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScCopySelection
//
// Synopsis: Copy the selected result item(s) to clipboard.
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScCopySelection ()
{
DECLARE_SC(sc, _T("CAMCView::ScCopySelection"));
sc = ScExecuteResultItemVerb(MMC_VERB_COPY, NULL);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScDeleteScopeNode
//
// Synopsis: Deletes the specified scope node (if given) or currently
// selected node.
//
// Arguments: [varScopeNode] - node to delete
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScDeleteScopeNode (VARIANT& varScopeNode)
{
DECLARE_SC(sc, _T("CAMCView::ScDeleteScopeNode"));
sc = ScExecuteScopeItemVerb(MMC_VERB_DELETE, varScopeNode, NULL);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScDeleteSelection
//
// Synopsis: Deletes the selected item(s) in result pane.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScDeleteSelection ()
{
DECLARE_SC(sc, _T("CAMCView::ScDeleteSelection"));
sc = ScExecuteResultItemVerb(MMC_VERB_DELETE, NULL);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScRenameScopeNode
//
// Synopsis: Rename the specified scope node (if given) or currently
// selected node with given new name.
//
// Arguments: [bstrNewName] - the new name
// [varScopeNode] - given node.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScRenameScopeNode (BSTR bstrNewName, VARIANT& varScopeNode)
{
DECLARE_SC(sc, _T("CAMCView::ScRenameScopeNode"));
sc = ScExecuteScopeItemVerb(MMC_VERB_RENAME, varScopeNode, bstrNewName);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScRenameSelectedItem
//
// Synopsis: Rename the selected result item with given new name.
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScRenameSelectedItem (BSTR bstrNewName)
{
DECLARE_SC(sc, _T("CAMCView::ScRenameSelectedItem"));
sc = ScExecuteResultItemVerb(MMC_VERB_RENAME, bstrNewName);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScRefreshScopeNode
//
// Synopsis: Refresh the specified scope node (if given) or currently
// selected node.
//
// Arguments: [varScopeNode] - given node.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScRefreshScopeNode (VARIANT& varScopeNode)
{
DECLARE_SC(sc, _T("CAMCView::ScRefreshScopeNode"));
sc = ScExecuteScopeItemVerb(MMC_VERB_REFRESH, varScopeNode, NULL);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScRefreshSelection
//
// Synopsis: Refresh the selected result item(s).
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScRefreshSelection ()
{
DECLARE_SC(sc, _T("CAMCView::ScRefreshSelection"));
sc = ScExecuteResultItemVerb(MMC_VERB_REFRESH, NULL);
if (sc)
return sc;
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_ScopeNodeContextMenu
*
* PURPOSE: Creates a context menu for a scope node and returns it.
*
* PARAMETERS:
* VARIANT varScopeNode :
* PPCONTEXTMENU ppContextMenu :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scget_ScopeNodeContextMenu(VARIANT& varScopeNode, PPCONTEXTMENU ppContextMenu, bool bMatchGivenNode /* = false*/)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_ContextMenu"));
NodePtr spNode;
// See if context menu for exactly the given node is asked for.
bool bMatchedGivenNode = false;
sc = ScGetOptionalScopeNodeParameter(varScopeNode, &spNode, bMatchedGivenNode);
if (sc)
return sc;
if ( (bMatchGivenNode) && (!bMatchedGivenNode) )
return ScFromMMC(IDS_NODE_NOT_FOUND);
if(sc)
return sc;
INodeCallback* spNodeCallback = GetNodeCallback();
sc = ScCheckPointers(spNode, ppContextMenu, spNodeCallback, GetTreeCtrl());
if(sc)
return sc.ToHr();
*ppContextMenu = NULL; // initialize output.
HNODE hNode = NULL;
sc = ScGetHNodeFromPNode(spNode, hNode);
if (sc)
return sc;
// tell the node callback to add menu items for the scope node.
sc = spNodeCallback->CreateContextMenu(spNode, hNode, ppContextMenu);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_SelectionContextMenu
*
* PURPOSE: Creates a context menu for the current selection and returns it.
*
* PARAMETERS:
* PPCONTEXTMENU ppContextMenu : [OUT]: The context menu object
*
* RETURNS:
* SC : error if no list exists, or there is nothing selected.
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scget_SelectionContextMenu( PPCONTEXTMENU ppContextMenu)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_SelectionContextMenu"));
sc = ScCheckPointers(ppContextMenu);
if(sc)
return sc;
if (!HasListOrListPad()) // not a list. Return error
return (sc = ScFromMMC(MMC_E_NOLIST));
INodeCallback* pNodeCallback = GetNodeCallback();
sc = ScCheckPointers(pNodeCallback);
if(sc)
return sc.ToHr();
CContextMenuInfo contextInfo; // the structure to pass to nodemgr
// common entries
contextInfo.m_pConsoleView = this;
// always use the temp verbs - cannot depend on what the active pane is
contextInfo.m_dwFlags = CMINFO_USE_TEMP_VERB;
int iIndex = -1;
HNODE hNode = GetSelectedNode();
ASSERT(hNode != NULL);
int cSel = m_pListCtrl->GetSelectedCount();
if(0 == cSel)
{
// no items selected, bail
return (sc = ScFromMMC(MMC_E_NO_SELECTED_ITEMS));
}
else if(1 == cSel)
{
// single selection
LPARAM lvData = LVDATA_ERROR;
iIndex = _GetLVSelectedItemData(&lvData);
ASSERT(iIndex != -1);
ASSERT(lvData != LVDATA_ERROR);
if (IsVirtualList())
{
// virtual list item in the result pane
contextInfo.m_eDataObjectType = CCT_RESULT;
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
contextInfo.m_bBackground = false;
contextInfo.m_bMultiSelect = false;
contextInfo.m_resultItemParam = iIndex;
contextInfo.m_iListItemIndex = iIndex;
}
else
{
CResultItem* pri = CResultItem::FromHandle (lvData);
if(!pri)
return (sc = E_UNEXPECTED);
if (pri->IsScopeItem())
{
// scope item in the result pane
contextInfo.m_eDataObjectType = CCT_SCOPE;
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
contextInfo.m_bBackground = FALSE;
contextInfo.m_hSelectedScopeNode = GetSelectedNode();
contextInfo.m_resultItemParam = NULL;
contextInfo.m_bMultiSelect = FALSE;
contextInfo.m_bScopeAllowed = TRUE;
// change the scope node on which the menu is to be displayed
hNode = pri->GetScopeNode();
}
else
{
// single result item in the result pane
contextInfo.m_eDataObjectType = CCT_RESULT;
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
contextInfo.m_bBackground = false;
contextInfo.m_bMultiSelect = false;
contextInfo.m_resultItemParam = lvData;
contextInfo.m_iListItemIndex = iIndex;
}
}
}
else
{
// multiselection
iIndex = INDEX_MULTISELECTION; // => MultiSelect
contextInfo.m_eDataObjectType = CCT_RESULT;
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
contextInfo.m_bBackground = false;
contextInfo.m_bMultiSelect = true;
contextInfo.m_resultItemParam = LVDATA_MULTISELECT;
contextInfo.m_iListItemIndex = iIndex;
}
sc = pNodeCallback->CreateSelectionContextMenu(hNode, &contextInfo, ppContextMenu);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScExecuteMenuItem
*
* PURPOSE: Executes the specified context menu item on the specified context menu
*
* PARAMETERS:
* PCONTEXTMENU pContextMenu :
* BSTR MenuItemPath : Either the language-independent path or the
* language-dependent path.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScExecuteMenuItem(PCONTEXTMENU pContextMenu, BSTR MenuItemPath)
{
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteMenuItem"));
sc = ScCheckPointers(MenuItemPath);
if(sc)
return sc;
sc = ScCheckPointers(pContextMenu, E_UNEXPECTED);
if(sc)
return sc;
// execute the menu item, if found.
MenuItemPtr spMenuItem;
sc = pContextMenu->get_Item(CComVariant(MenuItemPath), &spMenuItem);
if(sc.IsError() || sc == SC(S_FALSE)) // error or no item
return (sc = E_INVALIDARG); // did not find the menu item.
// recheck the pointer
sc = ScCheckPointers(spMenuItem, E_UNEXPECTED);
if (sc)
return sc;
// found - execute it
sc = spMenuItem->Execute();
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScExecuteSelectionMenuItem
*
* PURPOSE: Executes a context menu item on the selection.
*
* PARAMETERS:
* BSTR MenuItemPath : Either the language-independent path or the
* language-dependent path of the menu item.
*
* NOTE: This is an aggregate or utility function - it only uses other
* object model functions
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScExecuteSelectionMenuItem(BSTR MenuItemPath)
{
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteSelectionMenuItem"));
// get the context menu object
ContextMenuPtr spContextMenu;
sc = Scget_SelectionContextMenu(&spContextMenu);
if(sc)
return sc;
sc = ScExecuteMenuItem(spContextMenu, MenuItemPath);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScExecuteScopeNodeMenuItem
*
* PURPOSE: Executes a context menu item on the specified scope node. The parameter
* is the language independent path of the menu item
*
* PARAMETERS:
* BSTR MenuItemLanguageIndependentPath :
*
* NOTE: This is an aggregate or utility function - it only uses other
* object model functions
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScExecuteScopeNodeMenuItem(BSTR MenuItemPath, VARIANT &varScopeNode /* = ActiveScopeNode */)
{
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteScopeNodeMenuItem"));
// get the context menu object for exactly the given node.
ContextMenuPtr spContextMenu;
sc = Scget_ScopeNodeContextMenu(varScopeNode, &spContextMenu, /*bMatchGivenNode = */ true);
if (sc == ScFromMMC(IDS_NODE_NOT_FOUND))
{
sc = ScFromMMC(IDS_ACTION_COULD_NOTBE_COMPLETED);
return sc;
}
if(sc)
return sc;
sc = ScExecuteMenuItem(spContextMenu, MenuItemPath);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScExecuteShellCommand
*
* PURPOSE: Executes a shell command with the specified parameters in the
* specified directory with the correct window size
*
* PARAMETERS:
* BSTR Command :
* BSTR Directory :
* BSTR Parameters :
* BSTR WindowState :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScExecuteShellCommand(BSTR Command, BSTR Directory, BSTR Parameters, BSTR WindowState)
{
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteShellCommand"));
sc = ScCheckPointers(Command, Directory, Parameters, WindowState);
if(sc)
return sc;
INodeCallback *pNodeCallback = GetNodeCallback();
HNODE hNodeSel = GetSelectedNode();
sc = ScCheckPointers(pNodeCallback, hNodeSel, E_UNEXPECTED);
if(sc)
return sc;
sc = pNodeCallback->ExecuteShellCommand(hNodeSel, Command, Directory, Parameters, WindowState);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_ListViewMode
*
* PURPOSE: Returns the list view mode, if available.
*
* PARAMETERS:
* ListViewMode * pMode :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scget_ListViewMode(PLISTVIEWMODE pMode)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_ListViewMode"));
// check parameter
if(!pMode)
{
sc = E_INVALIDARG;
return sc;
}
if (!HasList())
return (ScFromMMC(MMC_E_NOLIST));
int mode = 0;
// translate it into an automation friendly enum
switch(GetViewMode())
{
default:
ASSERT( 0 && "Should not come here");
// fall thru.
case LVS_LIST:
*pMode = ListMode_List;
break;
case LVS_ICON:
*pMode = ListMode_Large_Icons;
break;
case LVS_SMALLICON:
*pMode = ListMode_Small_Icons;
break;
case LVS_REPORT:
*pMode = ListMode_Detail;
break;
case MMCLV_VIEWSTYLE_FILTERED:
*pMode = ListMode_Filtered;
break;
}
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scput_ListViewMode
*
* PURPOSE: Sets the list mode to the specified mode.
*
* PARAMETERS:
* ListViewMode mode :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scput_ListViewMode(ListViewMode mode)
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_ListViewMode"));
int nMode;
if (!HasList())
return (ScFromMMC(MMC_E_NOLIST));
switch (mode)
{
default:
sc = E_INVALIDARG;
return sc;
case ListMode_List:
nMode = LVS_LIST;
break;
case ListMode_Detail:
nMode = LVS_REPORT;
break;
case ListMode_Large_Icons:
nMode = LVS_ICON;
break;
case ListMode_Small_Icons:
nMode = LVS_SMALLICON;
break;
case ListMode_Filtered:
nMode = MMCLV_VIEWSTYLE_FILTERED;
break;
}
sc = ScChangeViewMode(nMode);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScBack
*
* PURPOSE: Invokes the Back command on the view.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScBack()
{
DECLARE_SC(sc, TEXT("CAMCView::ScBack"));
sc = ScWebCommand(CConsoleView::eWeb_Back);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScForward
*
* PURPOSE: Invokes the Forward command on the view.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScForward()
{
DECLARE_SC(sc, TEXT("CAMCView::ScForward"));
sc = ScWebCommand(CConsoleView::eWeb_Forward);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scput_StatusBarText
*
* PURPOSE: Sets the status bar text for the view
*
* PARAMETERS:
* BSTR StatusBarText :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scput_StatusBarText(BSTR StatusBarText)
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_StatusBarText"));
// check the in parameter
sc = ScCheckPointers(StatusBarText);
if(sc)
return sc;
CConsoleStatusBar *pStatusBar = m_ViewData.GetStatusBar();
sc = ScCheckPointers(pStatusBar, E_UNEXPECTED);
if(sc)
return sc;
USES_CONVERSION;
// set the status text
sc = pStatusBar->ScSetStatusText(OLE2T(StatusBarText));
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_Memento
*
* PURPOSE: Returns the XML version of the memento for the current view.
*
* PARAMETERS:
* PBSTR Memento : [out]: The memento
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scget_Memento(PBSTR Memento)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_Memento"));
sc = ScCheckPointers(Memento);
if(sc)
return sc;
// initialize the out parameter
*Memento = NULL;
CMemento memento;
sc = ScInitializeMemento(memento);
if(sc)
return sc;
std::wstring xml_contents;
sc = memento.ScSaveToString(&xml_contents);
if(sc)
return sc.ToHr();
// store the result
CComBSTR bstrBuff(xml_contents.c_str());
*Memento = bstrBuff.Detach();
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScViewMemento
*
* PURPOSE: Sets the view from the specified XML memento.
*
* PARAMETERS:
* BSTR Memento :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScViewMemento(BSTR Memento)
{
DECLARE_SC(sc, TEXT("CAMCView::ScViewMemento"));
sc = ScCheckPointers(Memento);
if(sc)
return sc;
CMemento memento;
sc = memento.ScLoadFromString(Memento);
if(sc)
return sc;
sc = ScViewMemento(&memento);
if (sc == ScFromMMC(IDS_NODE_NOT_FOUND))
return (sc = ScFromMMC(IDS_ACTION_COULD_NOTBE_COMPLETED));
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::Scget_CellContents
//
// Synopsis: Given row & column, get the text.
//
// Arguments: Node: - the row
// [Column] - 1 based column index
// [pbstrCellContents] - return value, contents of cell.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::Scget_CellContents (PNODE Node, long Column, PBSTR pbstrCellContents)
{
DECLARE_SC(sc, _T("CAMCView::Scget_CellContents"));
sc = ScCheckPointers(Node, pbstrCellContents);
if (sc)
return sc;
*pbstrCellContents = NULL;
if (!HasList())
return (ScFromMMC(MMC_E_NOLIST));
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// No need to check if we are in REPORT mode as columns exist
// even in other modes (small icon....).
int iItem = -1;
sc = m_pListCtrl->ScFindResultItem( Node, iItem );
if (sc)
return sc;
// Script uses 1- based index for columns & rows.
// ColCount are total # of cols.
if (m_pListCtrl->GetColCount() < Column)
return (sc = E_INVALIDARG);
CListCtrl& ctlList = m_pListCtrl->GetListCtrl();
CString strData = ctlList.GetItemText(iItem, Column-1 /*convert to zero-based*/);
*pbstrCellContents = strData.AllocSysString();
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScExportList
//
// Synopsis: Export the list view data to given file with given options.
//
// Arguments: [bstrFile] - File to save to.
// [exportoptions] - (Unicode, tab/comma delimited & selected rows only).
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScExportList (BSTR bstrFile, ExportListOptions exportoptions)
{
DECLARE_SC(sc, _T("CAMCView::ScExportList"));
if (SysStringLen(bstrFile) < 1)
return (sc = E_INVALIDARG);
if (!HasList())
return (ScFromMMC(MMC_E_NOLIST));
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
bool bUnicode = (exportoptions & ExportListOptions_Unicode);
bool bTabDelimited = (exportoptions & ExportListOptions_TabDelimited);
bool bSelectedRowsOnly = (exportoptions & ExportListOptions_SelectedItemsOnly);
USES_CONVERSION;
LPCTSTR lpszFileName = OLE2T(bstrFile);
sc = ScWriteExportListData(lpszFileName, bUnicode,
bTabDelimited, bSelectedRowsOnly,
false /*bShowErrorDialogs*/);
if (sc)
return (sc);
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScClose
*
* PURPOSE: Implements Wiew.Close method
*
* PARAMETERS:
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScClose()
{
DECLARE_SC(sc, TEXT("CAMCView::ScClose"));
// get the frame and the document
CChildFrame* pFrame = GetParentFrame();
CAMCDoc* pDoc = CAMCDoc::GetDocument();
sc= ScCheckPointers(pDoc, pFrame, E_FAIL);
if (sc)
return sc;
// count the views
int cViews = 0;
CAMCViewPosition pos = pDoc->GetFirstAMCViewPosition();
while (pos != NULL)
{
CAMCView* pView = pDoc->GetNextAMCView(pos);
if ((pView != NULL) && ++cViews >= 2)
break;
}
// prevent closing the document this way !!!
if (cViews == 1)
{
sc.FromMMC(IDS_CloseDocNotLastView);
return sc;
}
// if not closing last view, then give it
// a chance to clean up first.
// (if whole doc is closing CAMCDoc will handle
// closing all the views.)
/*
* Don't allow the user to close the last persisted view.
*/
if (IsPersisted() && (pDoc->GetNumberOfPersistedViews() == 1))
{
sc.FromMMC(IDS_CantCloseLastPersistableView);
return sc;
}
// checkings done, do close
// do it indirectly so that it won't hurt the view extension it it
// tries to close itself
pFrame->PostMessage(WM_CLOSE);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_ScopeTreeVisible
*
* PURPOSE: Implements get method for Wiew.ScopeTreeVisible property
*
* PARAMETERS:
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scget_ScopeTreeVisible( PBOOL pbVisible )
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_ScopeTreeVisible"));
// parameter check...
sc = ScCheckPointers(pbVisible);
if (sc)
return sc;
*pbVisible = IsScopePaneVisible();
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scput_ScopeTreeVisible
*
* PURPOSE: Implements set method for Wiew.ScopeTreeVisible property
*
* PARAMETERS:
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scput_ScopeTreeVisible( BOOL bVisible )
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_ScopeTreeVisible"));
// show/hide the scope pane
sc = ScShowScopePane (bVisible);
if (sc)
return (sc);
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::ScFindResultItemForScopeNode
*
* PURPOSE: - Calculates result item representing the scope node in the list
*
* PARAMETERS:
* PNODE pNode - node to search
* HRESULTITEM &itm - resulting item
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::ScFindResultItemForScopeNode( PNODE pNode, HRESULTITEM &itm )
{
DECLARE_SC(sc, TEXT("CAMCView::ScFindResultItemForScopeNode"));
// initialization
itm = NULL;
// parameter check
sc = ScCheckPointers(pNode);
if (sc)
return sc;
// get/check for list view and tree controls and callback
IScopeTree* const pScopeTree = GetScopeTreePtr();
sc = ScCheckPointers( pScopeTree, m_pTreeCtrl, m_spNodeCallback, E_UNEXPECTED);
if (sc)
return sc;
// retrieve MTNode
HMTNODE hMTNode = NULL;
sc = pScopeTree->GetHMTNode(pNode, &hMTNode);
if (sc)
return sc;
// get the pointer to the map
CTreeViewMap *pTreeMap = m_pTreeCtrl->GetTreeViewMap();
sc = ScCheckPointers(pTreeMap, E_UNEXPECTED);
if (sc)
return sc;
// find the tree item for the node
HTREEITEM htiNode = NULL;
sc = pTreeMap->ScGetHTreeItemFromHMTNode(hMTNode, &htiNode);
if (sc)
return sc = ScFromMMC(MMC_E_RESULT_ITEM_NOT_FOUND);
// try to match the node to the child of selected one
HTREEITEM htiParent = m_pTreeCtrl->GetParentItem(htiNode);
if (htiParent == NULL || htiParent != m_pTreeCtrl->GetSelectedItem())
return sc = ScFromMMC(MMC_E_RESULT_ITEM_NOT_FOUND);
// the node shold be in the ListView, lets find if!
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(htiNode);
// get result item id
sc = m_spNodeCallback->GetResultItem (hNode, &itm);
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::ScGetScopeNodeForItem
*
* PURPOSE: Returns Node (Scope Node) for specified item index
*
* PARAMETERS:
* int nItem - node index to retrieve
* PPNODE ppNode - result storage
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::ScGetScopeNode( HNODE hNode, PPNODE ppNode )
{
DECLARE_SC(sc, TEXT("CCCListViewCtrl::ScGetScopeNodeForItem"));
// check the parameters
sc = ScCheckPointers(ppNode);
if (sc)
return sc;
// initialize the result
*ppNode = NULL;
// get/check required pointers
IScopeTree* const pScopeTree = GetScopeTreePtr();
sc = ScCheckPointers(pScopeTree, m_spNodeCallback, E_UNEXPECTED);
if (sc)
return sc;
// find MTNode
HMTNODE hmtNode;
sc = m_spNodeCallback->GetMTNode(hNode, &hmtNode);
if (sc)
return sc;
// request the object!
sc = pScopeTree->GetMMCNode(hmtNode, ppNode);
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::Scget_Columns
*
* PURPOSE: create new or return pointer to existing Columns object
*
* PARAMETERS:
* PPCOLUMNS ppColumns - resulting (AddRef'ed) pointer
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::Scget_Columns(PPCOLUMNS ppColumns)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_Columns"));
// Check received parameters
sc = ScCheckPointers(ppColumns);
if (sc)
return sc;
// initialize
*ppColumns = NULL;
// Check the pointer to LV
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// forward the request to LV
sc = m_pListCtrl->Scget_Columns(ppColumns);
if (sc)
return sc;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScGetSelectedLVItem
//
// Synopsis: Return the LVItem cookie.
//
// Arguments: LPARAM - the LVDATA retval.
//
// Returns: SC - Fails if no selected item in LV.
//
//--------------------------------------------------------------------
SC CAMCView::ScGetSelectedLVItem(LPARAM& lvData)
{
DECLARE_SC(sc, _T("CAMCView::ScGetSelectedLVItem"));
lvData = LVDATA_ERROR;
int cSel = m_pListCtrl->GetSelectedCount();
if(0 == cSel)
{
// no items selected, bail
return (sc = ScFromMMC(MMC_E_NO_SELECTED_ITEMS));
}
else if(1 == cSel)
{
// single selection
int iIndex = _GetLVSelectedItemData(&lvData);
if (iIndex == -1 || lvData == LVDATA_ERROR)
return (sc = E_UNEXPECTED);
if (IsVirtualList())
{
// virtual list item in the result pane
lvData = iIndex;
}
}
else if (cSel > 1)
{
// multiselection
lvData = LVDATA_MULTISELECT;
}
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScGetHNodeFromPNode
//
// Synopsis: Takes in PNODE and returns corresponding hNode
//
// Arguments: [PNODE] - Given pnode.
// [HNODE] - ret val.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScGetHNodeFromPNode (const PNODE& pNode, HNODE& hNode)
{
DECLARE_SC(sc, _T("CAMCView::ScGetHNodeFromPNode"));
hNode = NULL;
CAMCTreeView* pAMCTreeView = GetTreeCtrl();
sc = ScCheckPointers(pAMCTreeView, E_UNEXPECTED);
if (sc)
return sc;
CTreeViewMap *pTreeMap = pAMCTreeView->GetTreeViewMap();
IScopeTree *pScopeTree = GetScopeTree();
sc = ScCheckPointers(pTreeMap, pScopeTree, E_UNEXPECTED);
if(sc)
return sc;
HMTNODE hMTNode = NULL;
sc = pScopeTree->GetHMTNode(pNode, &hMTNode);
if(sc)
return sc;
sc = pTreeMap->ScGetHNodeFromHMTNode(hMTNode, &hNode);
if(sc)
return sc;
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetMMCView
*
* PURPOSE: Creates, AddRef's, and returns a pointer to the tied COM object.
*
* PARAMETERS:
* View ** ppView :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScGetMMCView(View **ppView)
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetMMCView"));
sc = ScCheckPointers(ppView);
if (sc)
return sc;
// init out parameter
*ppView = NULL;
// create a CMMCView if needed.
sc = CTiedComObjectCreator<CMMCView>::ScCreateAndConnect(*this, m_spView);
if(sc)
return sc;
if(m_spView == NULL)
{
sc = E_UNEXPECTED;
return sc;
}
// addref the pointer for the client.
m_spView->AddRef();
*ppView = m_spView;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::IsDirty
*
* PURPOSE: Determines whether or not CAMCView is in a dirty state
*
* RETURNS:
* bool
*
*+-------------------------------------------------------------------------*/
bool CAMCView::IsDirty()
{
bool bRet = m_bDirty;
if (!m_bDirty && !m_fRootedAtNonPersistedDynamicNode)
bRet = HasNodeSelChanged();
TraceDirtyFlag(TEXT("CAMCView"), bRet);
return (bRet);
}
/////////////////////////////////////////////////////////////////////////////
// CAMCView drawing
void CAMCView::OnDraw(CDC* pDC)
{
if (IsScopePaneVisible())
{
pDC->FillRect (m_rectVSplitter, AMCGetSysColorBrush (COLOR_3DFACE));
}
}
/////////////////////////////////////////////////////////////////////////////
// CAMCView printing
BOOL CAMCView::OnPreparePrinting(CPrintInfo* pInfo)
{
TRACE_METHOD(CAMCView, OnPreparePrinting);
// default preparation
return DoPreparePrinting(pInfo);
}
void CAMCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
TRACE_METHOD(CAMCView, OnBeginPrinting);
}
void CAMCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
TRACE_METHOD(CAMCView, OnEndPrinting);
}
/////////////////////////////////////////////////////////////////////////////
// CAMCView diagnostics
#ifdef _DEBUG
void CAMCView::AssertValid() const
{
CView::AssertValid();
}
void CAMCView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CAMCDoc* CAMCView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAMCDoc)));
return (CAMCDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CAMCView message handlers
//+-------------------------------------------------------------------------
//
// Function: PreCreateWindow
//
// Synopsis: Create new window class (CAMCView) - WS_EX_CLIENTEDGE
//
//--------------------------------------------------------------------------
BOOL CAMCView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= WS_CLIPCHILDREN;
cs.style &= ~WS_BORDER;
// give base class a chance to do own job
BOOL bOK = (CView::PreCreateWindow(cs));
// register view class
LPCTSTR pszViewClassName = g_szAMCViewWndClassName;
// try to register window class which does not cause the repaint
// on resizing (do it only once)
static bool bClassRegistered = false;
if ( !bClassRegistered )
{
WNDCLASS wc;
if (::GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wc))
{
// Clear the H and V REDRAW flags
wc.style &= ~(CS_HREDRAW | CS_VREDRAW);
wc.lpszClassName = pszViewClassName;
// Register this new class;
bClassRegistered = AfxRegisterClass(&wc);
}
}
// change window class to one which does not cause the repaint
// on resizing if we successfully registered such
if ( bClassRegistered )
cs.lpszClass = pszViewClassName;
return bOK;
}
//+-------------------------------------------------------------------------
//
// Function: OnCreate
//
// Synopsis: Create Window, and Tree control / Default List control
//
//--------------------------------------------------------------------------
int CAMCView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
DECLARE_SC(sc, _T("CAMCView::OnCreate"));
if (CView::OnCreate(lpCreateStruct) == -1)
{
sc = E_FAIL;
return -1;
}
CChildFrame* pFrame = GetParentFrame();
ASSERT(NULL != pFrame);
if (pFrame)
pFrame->SetAMCView(this);
m_ViewData.SetStatusBar (dynamic_cast<CConsoleStatusBar*>(pFrame));
m_ViewData.SetConsoleView (this);
m_RightDescCtrl.Create (NULL, WS_CHILD, g_rectEmpty, this, IDC_RightDescBar);
ASSERT (m_pDocument != NULL);
ASSERT (m_pDocument == CAMCDoc::GetDocument());
ASSERT_KINDOF (CAMCDoc, m_pDocument);
CAMCDoc* pAMCDoc = reinterpret_cast<CAMCDoc *>(m_pDocument);
CCreateContext* pContext = (CCreateContext*) lpCreateStruct->lpCreateParams;
ASSERT (pContext != NULL);
// Set window options
m_ViewData.m_lWindowOptions = pAMCDoc->GetNewWindowOptions();
/*
* If the scope pane is suppressed, clear the scope-visible flag.
* It's not necessary to call ScShowScopePane here because none of
* the windows have been created yet. We just need to keep our
* interal accounting correct.
*/
if (m_ViewData.m_lWindowOptions & MMC_NW_OPTION_NOSCOPEPANE)
SetScopePaneVisible (false);
// Create tree ctrl.
if (!CreateView (IDC_TreeView) || (!m_pTreeCtrl) )
{
sc = E_FAIL;
return -1;
}
SetPane(ePane_ScopeTree, m_pTreeCtrl, uiClientEdge);
if (!AreStdToolbarsAllowed())
m_ViewData.m_dwToolbarsDisplayed &= ~(STD_MENUS | STD_BUTTONS);
// Create default list control
if (!CreateListCtrl (IDC_ListView, pContext))
{
sc = E_FAIL;
return -1;
}
// Create the folder tab control
if (!CreateFolderCtrls ())
{
sc = E_FAIL;
return -1;
}
// initialize the result pane to the list view
{
CResultViewType rvt;
sc = ScSetResultPane(NULL /*HNODE*/, rvt, MMCLV_VIEWSTYLE_REPORT /*viewMode*/, false /*bUsingHistory*/);
if(sc)
return -1;
}
sc = ScCreateToolbarObjects();
if (sc)
return -1;
//
// Set m_ViewData.
//
m_ViewData.m_nViewID = 0;// Set in OnInitialUpdate
VERIFY ((m_ViewData.m_spNodeManager = m_pTreeCtrl->m_spNodeManager) != NULL);
VERIFY ((m_ViewData.m_spResultData = m_pTreeCtrl->m_spResultData) != NULL);
VERIFY ((m_ViewData.m_spRsltImageList = m_pTreeCtrl->m_spRsltImageList) != NULL);
VERIFY ( m_ViewData.m_hwndView = m_hWnd);
VERIFY ( m_ViewData.m_hwndListCtrl = m_pListCtrl->GetListViewHWND());
VERIFY ( m_ViewData.m_pConsoleData = GetDocument()->GetConsoleData());
m_ViewData.m_pMultiSelection = NULL;
if(pFrame)
{
// add the MDIClient window's taskbar as an observer
CMDIFrameWnd * pFrameWnd = pFrame->GetMDIFrame();
CWnd *pWnd = NULL;
if(pFrameWnd)
pWnd = pFrameWnd->GetWindow(GW_CHILD); // get the first child of the frame.
}
// add AMCDoc as an observer for this source (object)
CAMCApp *pCAMCApp = AMCGetApp();
if ( pCAMCApp )
AddObserver(*static_cast<CAMCViewObserver *>(pCAMCApp));
// fire the view creation event to all observers.
sc = ScFireEvent(CAMCViewObserver::ScOnViewCreated, this);
if(sc)
sc.TraceAndClear();
return 0;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::CreateFolderCtrls
*
* PURPOSE: Creates the tabbed folder controls for the scope and result panes.
*
* RETURNS:
* bool
*
*+-------------------------------------------------------------------------*/
bool
CAMCView::CreateFolderCtrls()
{
if (!m_pResultFolderTabView->Create (WS_CHILD|WS_VISIBLE, g_rectEmpty, this, IDC_ResultTabCtrl))
return false;
// add the views to the framework
GetDocument()->AddView(m_pResultFolderTabView);
return true;
}
/*+-------------------------------------------------------------------------*
* CAMCView::CreateView
*
* This was copied largely from CFrameWnd::CreateView. We need to duplicate
* it here so common control-based views are initially created with the
* correct parent. A common control caches its original parent, so
* using CFrameWnd::CreateView (which will create the view with the frame
* as its parent) then reparenting to CAMCView will result in the common
* control caching the wrong parent.
*--------------------------------------------------------------------------*/
CView* CAMCView::CreateView (CCreateContext* pContext, int nID, DWORD dwStyle)
{
ASSERT(m_hWnd != NULL);
ASSERT(::IsWindow(m_hWnd));
ASSERT(pContext != NULL);
ASSERT(pContext->m_pNewViewClass != NULL);
CView* pView = (CView*)pContext->m_pNewViewClass->CreateObject();
if (pView == NULL)
{
TRACE1("Warning: Dynamic create of view type %hs failed.\n",
pContext->m_pNewViewClass->m_lpszClassName);
return NULL;
}
ASSERT_KINDOF(CView, pView);
// views are always created with a border!
if (!pView->Create (NULL, NULL, AFX_WS_DEFAULT_VIEW | dwStyle,
g_rectEmpty, this, nID, pContext))
{
TRACE0("Warning: could not create view for frame.\n");
return NULL; // can't continue without a view
}
return pView;
}
/*+-------------------------------------------------------------------------*
* CAMCView::CreateView
*
*
*--------------------------------------------------------------------------*/
bool CAMCView::CreateView (int nID)
{
struct CreateViewData
{
int nID;
CRuntimeClass* pClass;
CView** ppView;
DWORD dwStyle;
};
CreateViewData rgCreateViewData[] =
{
{ IDC_TreeView,
RUNTIME_CLASS(CAMCTreeView),
(CView**)&m_pTreeCtrl,
0 },
{ IDC_OCXHostView,
RUNTIME_CLASS(COCXHostView),
(CView**)&m_pOCXHostView,
0 },
{ IDC_WebViewCtrl,
RUNTIME_CLASS(CAMCWebViewCtrl),
(CView**)&m_pWebViewCtrl,
CAMCWebViewCtrl::WS_HISTORY | CAMCWebViewCtrl::WS_SINKEVENTS},
{ IDC_ViewExtensionView,
RUNTIME_CLASS(CAMCWebViewCtrl),
(CView**)&m_pViewExtensionCtrl,
WS_CLIPSIBLINGS },
};
for (int i = 0; i < countof (rgCreateViewData); i++)
{
if (rgCreateViewData[i].nID == nID)
{
CCreateContext ctxt;
ZeroMemory (&ctxt, sizeof (ctxt));
ctxt.m_pCurrentDoc = GetDocument();
ctxt.m_pNewViewClass = rgCreateViewData[i].pClass;
CView*& pView = *rgCreateViewData[i].ppView;
ASSERT (pView == NULL);
pView = CreateView (&ctxt, nID, rgCreateViewData[i].dwStyle);
ASSERT ((pView != NULL) && "Check the debug output window");
// Add observers only to tree, ocx and web hosts. Do not add to view extension host
// as we do not care about its activation/deactivations.
switch (nID)
{
case IDC_TreeView:
// set the view and the description bar as observers of the tree view control
m_pTreeCtrl->AddObserver(static_cast<CTreeViewObserver &>(*this));
m_pTreeCtrl->AddObserver(static_cast<CTreeViewObserver &>(m_RightDescCtrl));
break;
case IDC_OCXHostView:
m_pOCXHostView->AddObserver(static_cast<COCXHostActivationObserver &>(*this));
break;
case IDC_WebViewCtrl:
m_pWebViewCtrl->AddObserver(static_cast<COCXHostActivationObserver &>(*this));
break;
}
return (pView != NULL);
}
}
ASSERT (false && "Missing an entry in rgCreateViewData");
return (false);
}
/*+-------------------------------------------------------------------------*
* CAMCView::GetActiveView
*
*
*--------------------------------------------------------------------------*/
CAMCView* CAMCView::GetActiveView()
{
return NULL;
}
/*+-------------------------------------------------------------------------*
* CAMCView::ScChangeViewMode
*
*
*--------------------------------------------------------------------------*/
SC CAMCView::ScChangeViewMode (int nNewMode)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC (sc, _T("CAMCView::OnViewModeChange"));
// if switching from a custom view, force a reselect
if (!HasListOrListPad())
{
NavState state = m_pHistoryList->GetNavigateState();
m_pHistoryList->SetNavigateState (MMC_HISTORY_BUSY);
PrivateChangeListViewMode(nNewMode);
m_pHistoryList->SetNavigateState (state);
sc = m_pTreeCtrl->ScReselect();
if (sc)
return sc;
}
else
{
int nCurMode = m_pListCtrl->GetViewMode();
if ( (nNewMode == MMCLV_VIEWSTYLE_FILTERED) &&
(!(GetListOptions() & RVTI_LIST_OPTIONS_FILTERED)) )
return (sc = E_INVALIDARG);
PrivateChangeListViewMode(nNewMode);
// if filter state change, notify the snap-in
if ( ((nCurMode == MMCLV_VIEWSTYLE_FILTERED) != (nNewMode == MMCLV_VIEWSTYLE_FILTERED))
&& (GetListOptions() & RVTI_LIST_OPTIONS_FILTERED))
{
HNODE hNodeSel = GetSelectedNode();
ASSERT(hNodeSel != NULL);
m_spNodeCallback->Notify(hNodeSel, NCLBK_FILTER_CHANGE,
(nNewMode == MMCLV_VIEWSTYLE_FILTERED) ? MFCC_ENABLE : MFCC_DISABLE, 0);
}
}
return (sc);
}
/*+-------------------------------------------------------------------------*
* CAMCView::ViewMmento
*
*
*--------------------------------------------------------------------------*/
SC CAMCView::ScViewMemento(CMemento* pMemento)
{
DECLARE_SC (sc, TEXT("CAMCView::ScViewMemento"));
sc = ScCheckPointers(pMemento);
if (sc)
return sc;
AFX_MANAGE_STATE (AfxGetAppModuleState());
IScopeTree* const pScopeTree = GetScopeTreePtr();
sc = ScCheckPointers(pScopeTree, E_UNEXPECTED);
if (sc)
return sc;
MTNODEID NodeId = 0;
CBookmark& bm = pMemento->GetBookmark();
ASSERT(bm.IsValid());
// We want to display message if exact favorite item cannot be selected.
bool bExactMatchFound = false; // out value from GetNodeIDFromBookmark.
sc = pScopeTree->GetNodeIDFromBookmark( bm, &NodeId, bExactMatchFound);
if(sc)
return sc;
if (! bExactMatchFound)
return ScFromMMC(IDS_NODE_NOT_FOUND); // do not trace
INodeCallback *pNodeCallback = GetNodeCallback();
sc = ScCheckPointers(pNodeCallback, E_UNEXPECTED);
if (sc)
return sc;
// set the persisted information to the saved settings.
sc = pNodeCallback->SetViewSettings(GetViewID(),
reinterpret_cast<HBOOKMARK>(&bm),
reinterpret_cast<HVIEWSETTINGS>(&pMemento->GetViewSettings()));
if (sc)
return sc;
sc = ScSelectNode(NodeId, /*bSelectExactNode*/ true);
if (sc == ScFromMMC(IDS_NODE_NOT_FOUND))
{
SC scNoTrace = sc;
sc.Clear();
return scNoTrace;
}
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnSetFocus
*
* WM_SETFOCUS handler for CAMCView.
*--------------------------------------------------------------------------*/
void CAMCView::OnSetFocus(CWnd* pOldWnd)
{
/*
* try to deflect the activation to a child view; if we couldn't just punt
*/
if (!DeflectActivation (true, NULL))
CView::OnSetFocus(pOldWnd);
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnActivateView
*
*
*--------------------------------------------------------------------------*/
void CAMCView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
/*
* try to deflect the activation to a child view; if we couldn't just punt
*/
if (!DeflectActivation (bActivate, pDeactiveView))
CView::OnActivateView (bActivate, pActivateView, pDeactiveView);
}
/*+-------------------------------------------------------------------------*
* CAMCView::DeflectActivation
*
*
*--------------------------------------------------------------------------*/
bool CAMCView::DeflectActivation (BOOL fActivate, CView* pDeactivatingView)
{
if (fActivate)
{
CFrameWnd* pFrame = GetParentFrame();
if (pFrame == NULL)
return (false);
/*
* first try to put the focus back on the deactivating view
*/
if (pDeactivatingView == NULL)
pDeactivatingView = pFrame->GetActiveView();
if ((pDeactivatingView != NULL) && (pDeactivatingView != this))
{
pFrame->SetActiveView (pDeactivatingView);
return true;
}
/*
* otherwise, deflect the activation to the scope view, if it's there
*/
CView* pScopeView = NULL;
if (IsScopePaneVisible() && ((pScopeView = GetPaneView(ePane_ScopeTree)) != NULL))
{
if (IsWindow (pScopeView->GetSafeHwnd()))
{
pFrame->SetActiveView (pScopeView);
return (true);
}
}
/*
* finally, no scope view, try the result view
*/
CView* pResultView = GetResultView();
if (pResultView != NULL)
{
pFrame->SetActiveView(pResultView);
return (true);
}
}
return (false);
}
//+-------------------------------------------------------------------------
//
// Function: OnLButtonDown
//
// Synopsis: If mouse down in splitter area initiate view tracker to move
// the splitter. (TrackerCallback function handles completion)
//--------------------------------------------------------------------------
void CAMCView::OnLButtonDown(UINT nFlags, CPoint pt)
{
TRACE_METHOD(CAMCView, OnLButtonDown);
// click in splitter bar?
if (!m_rectVSplitter.PtInRect(pt))
return;
// setup tracker information
TRACKER_INFO trkinfo;
// range is client area
GetClientRect(trkinfo.rectArea);
// bound by min size of panes
trkinfo.rectBounds = trkinfo.rectArea;
trkinfo.rectBounds.left += m_PaneInfo[ePane_ScopeTree].cxMin;
trkinfo.rectBounds.right -= m_PaneInfo[ePane_Results].cxMin;
// Current tracker is splitter rect
trkinfo.rectTracker = trkinfo.rectArea;
trkinfo.rectTracker.left = m_PaneInfo[ePane_ScopeTree].cx;
trkinfo.rectTracker.right = trkinfo.rectTracker.left + m_cxSplitter;
// Don't allow either pane to be hidden by dragging the splitter
trkinfo.bAllowLeftHide = FALSE;
trkinfo.bAllowRightHide = FALSE;
// back ptr and completion callback
trkinfo.pView = this;
trkinfo.pCallback = TrackerCallback;
// initiate tracking
CViewTracker::StartTracking (&trkinfo);
}
void CAMCView::AdjustTracker (int cx, int cy)
{ // if user resizes window so that splitter becomes hidden,
// move it like Explorer does.
if (!IsScopePaneVisible())
return;
// extra adjustment
cx -= BORDERPADDING + 1;
if (cx <= m_PaneInfo[ePane_ScopeTree].cx + m_cxSplitter)
{
int offset = m_PaneInfo[ePane_ScopeTree].cx + m_cxSplitter - cx;
m_PaneInfo[ePane_ScopeTree].cx -= offset;
m_PaneInfo[ePane_Results].cx -= offset;
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
}
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScAddDefaultColumns
*
* PURPOSE:
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScAddDefaultColumns()
{
DECLARE_SC(sc, TEXT("CAMCView::ScAddDefaultColumns"));
IHeaderCtrlPtr spHeaderCtrl = m_ViewData.m_spNodeManager;
sc = ScCheckPointers(spHeaderCtrl, E_UNEXPECTED);
if(sc)
return sc;
SetUsingDefColumns(TRUE);
const int INDEX_MAX = 2;
CString str[INDEX_MAX];
LoadString(str[0], IDS_NAME);
LoadString(str[1], IDS_TYPE);
int iMax = 0;
int nMax = str[0].GetLength();
int nTemp = 0;
for (int i=1; i < INDEX_MAX; i++)
{
nTemp = str[i].GetLength();
if (nTemp > nMax)
{
nMax = nTemp;
iMax = i;
}
}
LPOLESTR psz = new OLECHAR[nMax + 1];
int alWidths[INDEX_MAX] = {0, 0};
GetDefaultColumnWidths(alWidths);
for (i=0; i < INDEX_MAX; i++)
{
// Bug 157408: remove the "Type" column for static nodes
if (i == 1)
continue;
USES_CONVERSION;
wcscpy(psz, T2COLE( (LPCTSTR) str[i] ));
sc = spHeaderCtrl->InsertColumn(i, psz, LVCFMT_LEFT, alWidths[i]);
if(sc)
return sc;
}
delete [] psz;
return sc;
}
SC
CAMCView::ScInitDefListView(LPUNKNOWN pUnkResultsPane)
{
DECLARE_SC(sc, TEXT("CAMCView::ScInitDefListView"));
if (!HasList())
return (sc = E_UNEXPECTED);
sc = ScCheckPointers(pUnkResultsPane, m_ViewData.m_spResultData, E_UNEXPECTED);
if(sc)
return sc;
m_ViewData.m_spResultData->ResetResultData();
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnSelectNode
*
* Most of this code was moved out of CAMCTreeView::OnSelectNode, as it is
* more appropriate that this is executed by CAMCView.
*
* PURPOSE: Called when an item in the tree is selected. Does the following:
* 1) Sets up the result pane to either a list, and OCX, or a web page.
* 2) Sets the view options
* 3) Sends a selection notification to the node.
* 3) Adds a history entry if needed.
*
* PARAMETERS:
* HNODE hNode : [IN]: The node that got selected.
* BOOL & bAddSubFolders : [OUT]: Whether subfolders should be added to the list
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnSelectNode(HNODE hNode, BOOL &bAddSubFolders)
{
DECLARE_SC(sc, TEXT("CAMCView::ScOnSelectNode"));
USES_CONVERSION;
//
// Set the result pane
//
LPOLESTR pszResultPane = NULL;
GUID guidTaskpad = GUID_NULL;
int lViewMode = MMCLV_VIEWSTYLE_REPORT; // the default view mode
//long lViewOptions = MMC_VIEW_OPTIONS_NONE;
bool bUsingHistory = false;
bool bRestoredView = false;
INodeCallback* spNodeCallBack = GetNodeCallback();
sc = ScCheckPointers(spNodeCallBack, E_UNEXPECTED);
if (sc)
return sc;
CHistoryList* pHistoryList = GetHistoryList();
sc = ScCheckPointers(pHistoryList, E_UNEXPECTED);
if (sc)
return sc;
CResultViewType rvt;
if (pHistoryList->GetNavigateState() == MMC_HISTORY_NAVIGATING)
{
// we're going "back" or "forward":
// get Result pane stuff from history
bUsingHistory = true;
sc = pHistoryList->ScGetCurrentResultViewType(rvt, lViewMode, guidTaskpad);
if (sc)
return sc;
sc = spNodeCallBack->RestoreResultView(hNode, rvt);
if (sc)
{
TraceError(_T("Snapin failed on NCLBK_RESTORE_VIEW\n"), sc);
sc.Clear(); // Compatible with 1.2 dont need this error.
}
if (sc.ToHr() == S_OK)
bRestoredView = true;
else
rvt = CResultViewType(); // this restores rvt back to a nascent state. see Bug 176058.
}
// The view is not restored by history so ask snapin for view settings.
if (! bRestoredView)
{
// get Result pane stuff from snapin
GUID guid = GUID_NULL;
sc = spNodeCallBack->GetResultPane(hNode, rvt, &guid);
if (sc)
return sc;
// we cannot pass the guidTaskpad to GetResultPane directly, since
// when it is navigation what causes the change, view settings are
// not yet updated and thus the guid returned will not reflect the
// current situation
if (!bUsingHistory)
guidTaskpad = guid;
}
// make sure we have a taskpad set (this will change the value of guidTaskpad if required)
// This is required when pages referred from history are no longer available when returning
// to the view (taskpad being deleted/default page being replaced/etc.)
if (bUsingHistory)
spNodeCallBack->SetTaskpad(hNode, &guidTaskpad);
//SetViewOptions(lViewOptions);
// at this stage, rvt contains all the result view information (excluding, as always the list view mode.)
if (rvt.HasList())
{
SetListViewMultiSelect(
(rvt.GetListOptions() & RVTI_LIST_OPTIONS_MULTISELECT) == RVTI_LIST_OPTIONS_MULTISELECT);
}
sc = ScSetResultPane(hNode, rvt, lViewMode, bUsingHistory);
if(sc)
return sc;
::CoTaskMemFree(pszResultPane);
//
// Initialize default list view.
//
LPUNKNOWN pUnkResultsPane = GetPaneUnknown(CConsoleView::ePane_Results);
if (rvt.HasList())
{
sc = ScInitDefListView(pUnkResultsPane);
if(sc)
return sc;
sc = ScCheckPointers(m_ViewData.m_spResultData, E_UNEXPECTED);
if (sc)
return sc;
// this turns off list view redrawing. Should have some sort of smart object that automatically
// turns redrawing on in its destructor.
m_ViewData.m_spResultData->SetLoadMode(TRUE); // SetLoadMode(FALSE) is called by the caller, CAMCTreeView::OnSelectNode
}
//
// Notify the new node that it is selected.
//
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = TRUE;
selInfo.m_pView = pUnkResultsPane;
if (rvt.HasWebBrowser())
{
selInfo.m_bResultPaneIsWeb = TRUE;
selInfo.m_lCookie = LVDATA_CUSTOMWEB;
}
else if (rvt.HasOCX())
{
selInfo.m_bResultPaneIsOCX = TRUE;
selInfo.m_lCookie = LVDATA_CUSTOMOCX;
}
// Increment and save local copy of nesting level counter. This counter serves
// two purposes. First, it allows AMCView to inhibit inserting scope items in
// the result pane during a select by checking the IsSelectingNode method.
// Without this test the scope items would appear twice because all the scope
// items are added to the result pane at the end of this method.
// Second, during the following ScNotifySelect call the snap-in could do another
// select which would re-enter this method. In that case, only the innermost
// call to this method should do the post-notify processing. The outer calls
// should just exit, returning S_FALSE instead of S_OK.
int nMyNestLevel = ++m_nSelectNestLevel;
// collect / manage view tabs
sc = ScAddFolderTabs( hNode, guidTaskpad );
if (sc)
return sc;
try
{
sc = ScNotifySelect ( spNodeCallBack, hNode, false /*fMultiSelect*/, true, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
catch(...)
{
// if first call to Select, reset level to zero before leaving
if (nMyNestLevel == 1) m_nSelectNestLevel = 0;
throw;
}
// if the local call level does not match the shared call level then this
// method was reentered during the ScNotifySelect. In that case don't finish
// the processing because the node and/or view may have changed.
// Be sure to reset the call level to zero if this is the outermost call.
ASSERT(nMyNestLevel <= m_nSelectNestLevel);
BOOL bDoProcessing = (nMyNestLevel == m_nSelectNestLevel);
if (nMyNestLevel == 1)
m_nSelectNestLevel = 0;
if (!bDoProcessing)
return S_FALSE;
//
// If the result pane is the def-LV, ensure that there are headers.
// If not add the default ones
//
if (rvt.HasList())
{
SetUsingDefColumns(FALSE);
// Get ptr to ResultPane.
IMMCListViewPtr pMMCLV = pUnkResultsPane;
sc = ScCheckPointers(pMMCLV, E_UNEXPECTED);
if (sc)
return sc;
int nCols = 0;
sc = pMMCLV->GetColumnCount(&nCols);
if (sc)
return sc;
if(0 == nCols)
{
sc = ScAddDefaultColumns();
if(sc)
return sc;
IResultDataPrivatePtr& pResultDataPrivate = m_ViewData.m_spResultData;
sc = ScCheckPointers(pResultDataPrivate, E_UNEXPECTED);
if (sc)
return sc;
long lViewMode = GetViewMode();
// If default mode is filtered and new node doesn't
// support that, use report mode instead
if (lViewMode == MMCLV_VIEWSTYLE_FILTERED &&
!(rvt.GetListOptions() & RVTI_LIST_OPTIONS_FILTERED))
lViewMode = LVS_REPORT;
// you've got to change the mode before you change the
// style: style doesn't contain the "quickfilter" bit.
pResultDataPrivate->SetViewMode (lViewMode);
long style = GetDefaultListViewStyle();
if (style != 0)
{
sc = pResultDataPrivate->SetListStyle(style);
if (sc)
return sc;
}
}
}
//
// Show the static scope items in the result pane,
// but not for a virtual list view, or views specifically
// marked that they don't want scope items in the result view
//
if (rvt.HasList() &&
!(rvt.GetListOptions() & RVTI_LIST_OPTIONS_OWNERDATALIST) &&
!(rvt.GetListOptions() & RVTI_LIST_OPTIONS_EXCLUDE_SCOPE_ITEMS_FROM_LIST))
{
bAddSubFolders = TRUE;
}
// Update window title.
sc = ScUpdateWindowTitle();
if(sc)
return sc;
// fire event to script
sc = ScFireEvent(CAMCViewObserver::ScOnViewChange, this, hNode);
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScSetResultPane
*
* PURPOSE: Sets the result pane to the specified configuration.
*
* PARAMETERS:
* HNODE hNode :
* CResultViewType rvt :
* long lViewOptions :
* bool bUsingHistory :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScSetResultPane(HNODE hNode, CResultViewType rvt, int viewMode, bool bUsingHistory)
{
DECLARE_SC(sc, TEXT("CAMCView::SetResultPane"));
m_ViewData.SetResultViewType(rvt);
if(rvt.HasList())
{
sc = ScAttachListViewAsResultPane();
if(sc)
return sc;
}
else if(rvt.HasWebBrowser())
{
sc = ScAttachWebViewAsResultPane();
if(sc)
return sc;
}
else if(rvt.HasOCX())
{
sc = ScAttachOCXAsResultPane(hNode);
if(sc)
return sc;
}
else
{
ASSERT(0 && "Should not come here!!");
return (sc = E_UNEXPECTED);
}
// show the toolbars
if(GetStdToolbar() != NULL) // may be NULL at startup.
{
sc = GetStdToolbar()->ScShowStdBar(true);
if(sc)
return sc;
}
// if we haven't gotten here using history, add a history entry.
if(!bUsingHistory)
{
GUID guidTaskpad = GUID_NULL;
GetTaskpadID(guidTaskpad);
sc = m_pHistoryList->ScAddEntry(rvt, m_nViewMode, guidTaskpad);
if(sc)
return sc;
}
// if we have a node manager, tell it what the result pane is.
if(m_ViewData.m_spNodeManager)
{
LPUNKNOWN pUnkResultsPane = GetPaneUnknown(CConsoleView::ePane_Results);
m_ViewData.m_spNodeManager->SetResultView(pUnkResultsPane);
}
return sc;
}
BOOL CAMCView::CreateListCtrl(int nID, CCreateContext* pContext)
{
TRACE_METHOD(CAMCView, CreateListCtrl);
ASSERT(m_pListCtrl == NULL);
CComObject<CCCListViewCtrl> *pLV = NULL;
CComObject<CCCListViewCtrl>::CreateInstance( &pLV );
if (pLV == NULL)
{
ASSERT(0 && "Unable to create list control");
return FALSE;
}
// we assign directly - implicit cast works, since we have a type derived from the one we need
m_pListCtrl = pLV;
// we intend to hold a reference, so do addref here (CreateInstance creates w/ 0 reffs)
m_pListCtrl->AddRef();
if (!m_pListCtrl->Create (WS_VISIBLE | WS_CHILD, g_rectEmpty, this, nID, pContext))
{
ASSERT(0 && "Unable to create list control");
return FALSE;
}
m_pListCtrl->SetViewMode (m_nViewMode);
SC SC = m_pListCtrl->ScInitialize(); // intialize the list control
return TRUE;
}
void CAMCView::SetListViewOptions(DWORD dwListOptions)
{
TRACE_METHOD(CAMCView, SetListViewOptions);
bool bVirtual = (dwListOptions & RVTI_LIST_OPTIONS_OWNERDATALIST) ? true : false;
ASSERT(m_pListCtrl != NULL);
CDocument* pDoc = GetDocument();
ASSERT(pDoc != NULL);
// If change to/from virtual list, change list mode
if (IsVirtualList() != bVirtual)
{
m_ViewData.SetVirtualList (bVirtual);
pDoc->RemoveView(m_pListCtrl->GetListViewPtr());
m_pListCtrl->SetVirtualMode(bVirtual);
pDoc->AddView(m_pListCtrl->GetListViewPtr());
m_ViewData.m_hwndListCtrl = m_pListCtrl->GetListViewHWND();
}
// if snapin doesn't support filtering make sure it's off
if (!(GetListOptions() & RVTI_LIST_OPTIONS_FILTERED) &&
m_pListCtrl->GetViewMode() == MMCLV_VIEWSTYLE_FILTERED)
{
m_pListCtrl->SetViewMode(LVS_REPORT);
}
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScAttachListViewAsResultPane
*
* PURPOSE: Sets up the list view as the result pane.
*
* PARAMETERS: NONE
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScAttachListViewAsResultPane()
{
DECLARE_SC(sc, TEXT("CAMCView::ScAttachListViewAsResultPane"));
bool bVirtual = (GetListOptions() & RVTI_LIST_OPTIONS_OWNERDATALIST) ? true : false;
GUID guidTaskpad;
GetTaskpadID(guidTaskpad);
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if(sc)
return sc;
CDocument* pDoc = GetDocument();
ASSERT(pDoc != NULL);
// If change to/from virtual list, change list mode
if (IsVirtualList() != bVirtual)
{
m_ViewData.SetVirtualList (bVirtual);
pDoc->RemoveView(m_pListCtrl->GetListViewPtr());
m_pListCtrl->SetVirtualMode(bVirtual);
pDoc->AddView(m_pListCtrl->GetListViewPtr());
m_ViewData.m_hwndListCtrl = m_pListCtrl->GetListViewHWND();
}
// if snapin doesn't support filtering make sure it's off
if (!(GetListOptions() & RVTI_LIST_OPTIONS_FILTERED) &&
m_pListCtrl->GetViewMode() == MMCLV_VIEWSTYLE_FILTERED)
{
m_pListCtrl->SetViewMode(LVS_REPORT);
}
ShowResultPane(m_pListCtrl->GetListViewPtr(), uiClientEdge);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScAttachWebViewAsResultPane
*
* PURPOSE:
*
* PARAMETERS: NONE
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScAttachWebViewAsResultPane()
{
DECLARE_SC(sc, TEXT("CAMCView::ScAttachWebViewAsResultPane"));
// if we were in ListPad-mode, undo that.
if (m_pListCtrl->IsListPad())
{
sc = m_pListCtrl->ScAttachToListPad (NULL, NULL);
if(sc)
return sc;
}
// The control is created on demand. This prevents IE from loading when unnecessary
// and reduces startup time.
if (m_pWebViewCtrl == NULL)
CreateView (IDC_WebViewCtrl);
sc = ScCheckPointers(m_pWebViewCtrl, E_UNEXPECTED);
if(sc)
return sc;
// Force web control to update its palette
SendMessage(WM_QUERYNEWPALETTE);
ShowResultPane(m_pWebViewCtrl, uiNoClientEdge);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScAttachOCXAsResultPane
*
* PURPOSE:
*
* PARAMETERS:
* LPCTSTR pszResultPane :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScAttachOCXAsResultPane(HNODE hNode)
{
DECLARE_SC(sc, TEXT("CAMCView::ScAttachOCXAsResultPane"));
USES_CONVERSION;
ASSERT(m_pListCtrl != NULL);
if (m_pOCXHostView == NULL)
CreateView (IDC_OCXHostView);
sc = ScCheckPointers(m_pOCXHostView);
if(sc)
return sc;
sc = m_pOCXHostView->ScSetControl(hNode, m_ViewData.m_rvt, GetNodeCallback());
if(sc)
return sc;
ShowResultPane(m_pOCXHostView, uiClientEdge);
return sc;
}
/*+-------------------------------------------------------------------------*
* CAMCView::ScApplyViewExtension
*
* Applies a view extension to the current view. pszURL specifies the
* URL of the HTML to load as the view extension. If pszURL is NULL or
* empty, the view extension is removed.
*
* This method will force a layout of the view if it is required.
*--------------------------------------------------------------------------*/
SC CAMCView::ScApplyViewExtension (
LPCTSTR pszURL) /* I:URL to use, NULL to remove */
{
DECLARE_SC (sc, _T("CAMCView::ScApplyViewExtension"));
/*
* assume no view extension
*/
bool fViewWasExtended = m_fViewExtended;
m_fViewExtended = false;
/*
* if we're given a URL with which to extend the view, turn on the extension
*/
if ((pszURL != NULL) && (*pszURL != 0))
{
/*
* if we don't have a web control for the view extension yet, create one
*/
if (m_pViewExtensionCtrl == NULL)
CreateView (IDC_ViewExtensionView);
sc = ScCheckPointers (m_pViewExtensionCtrl, E_FAIL);
if (sc)
return (sc);
m_fViewExtended = true;
// hide the hosted window initially
CWnd *pwndHosted = GetPaneView(ePane_Results);
sc = ScCheckPointers(pwndHosted);
if(sc)
return sc;
pwndHosted->ShowWindow(SW_HIDE);
RecalcLayout(); // do this BEFORE calling Navigate, which may resize the above rectangle via the mmcview behavior
// navigate to the requested URL
m_pViewExtensionCtrl->Navigate (pszURL, NULL);
}
else if (fViewWasExtended && (m_pViewExtensionCtrl != NULL))
{
/*
* Bug 96948: If we've got an extension and we're currently extending
* the view, navigate the view extension's web browser to an empty page
* so the behavior that resizes the hosted result frame is disabled
*/
CStr strEmptyPage;
sc = ScGetPageBreakURL (strEmptyPage);
if (sc)
return (sc);
m_pViewExtensionCtrl->Navigate (strEmptyPage, NULL);
if(fViewWasExtended)
DeferRecalcLayout();
}
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ShowResultPane
*
* PURPOSE:
*
* PARAMETERS:
* CView* pNewView :
* EUIStyleType nStyle :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CAMCView::ShowResultPane(CView* pNewView, EUIStyleType nStyle)
{
TRACE_METHOD(CAMCView, ShowResultPane);
ASSERT(pNewView != NULL);
CView* pCurrentView = GetPaneView(ePane_Results);
bool bActive = (GetParentFrame()->GetActiveView() == pCurrentView);
// Check to see if we need to swap the CWnd control in the result pane
if (pNewView != pCurrentView)
{
HWND hwndCurrentView = pCurrentView->GetSafeHwnd();
if (IsWindow (hwndCurrentView))
{
pCurrentView->ShowWindow(SW_HIDE);
// Note: We are directly hiding the window for cases that controls
// don't hide during a DoVerb(OLEIVERB_HIDE). Actually, this does a
// hide on all windows. It's too hard at this point to optimize the code
// for doing this with an OLE control only.
::ShowWindow(hwndCurrentView, SW_HIDE);
}
SetPane(ePane_Results, pNewView, nStyle);
RecalcLayout();
// if other pane was active, make the new one active
if ((pCurrentView != NULL) && bActive)
{
// make sure the new window is visible
pNewView->ShowWindow(SW_SHOW);
GetParentFrame()->SetActiveView(pNewView);
}
}
}
//+-------------------------------------------------------------------------
//
// Function: GetPaneInfo
//
// Synopsis: Get information about a particular pane
//
//--------------------------------------------------------------------------
void CAMCView::GetPaneInfo(ViewPane ePane, int* pcxCur, int* pcxMin)
{
TRACE_METHOD(CAMCView, GetPaneInfo);
ASSERT_VALID(this);
if (!IsValidPane (ePane))
{
ASSERT (false && "CAMCView::GetPaneInfo: Invalid pane specifier");
return;
}
if ((pcxCur==NULL) || (pcxMin==NULL))
{
ASSERT(FALSE); // One or more of the args is wrong
return;
}
// REVIEW fix enum
*pcxCur = m_PaneInfo[ePane].cx;
*pcxMin = m_PaneInfo[ePane].cxMin;
}
//+-------------------------------------------------------------------------
//
// Function: SetPaneInfo
//
// Synopsis: Set information about a particular pane
//
//--------------------------------------------------------------------------
void CAMCView::SetPaneInfo(ViewPane ePane, int cxCur, int cxMin)
{
TRACE_METHOD(CAMCView, SetPaneInfo);
ASSERT_VALID(this);
if (!IsValidPane (ePane))
{
ASSERT (false && "CAMCView::SetPaneInfo: Invalid pane specifier");
return;
}
if (cxCur < 0 || cxMin < 0)
{
ASSERT(FALSE); // One or more of the args is wrong
return;
}
m_PaneInfo[ePane].cx = cxCur;
m_PaneInfo[ePane].cxMin = cxMin;
}
//+-------------------------------------------------------------------------
//
// Function: GetPaneView
//
// Synopsis: Returns a pointer to CView for a particular pane
//
//--------------------------------------------------------------------------
CView* CAMCView::GetPaneView(ViewPane ePane)
{
TRACE_METHOD(CAMCView, GetPaneView);
ASSERT_VALID(this);
if (!IsValidPane (ePane))
{
ASSERT (false && "CAMCView::GetPaneView: Invalid pane specifier");
return (NULL);
}
return (m_PaneInfo[ePane].pView);
}
/*+-------------------------------------------------------------------------*
* CAMCView::GetResultView
*
*
*--------------------------------------------------------------------------*/
CView* CAMCView::GetResultView() const
{
CView* pView = NULL;
// may need changes here - assumes the different types are independent.
if(HasWebBrowser())
pView = m_pWebViewCtrl;
else if(HasList())
pView = m_pListCtrl->GetListViewPtr();
else if(HasOCX())
pView = m_pOCXHostView;
ASSERT (pView != NULL);
return (pView);
}
//+-------------------------------------------------------------------------
//
// Function: GetPaneUnknown
//
// Synopsis: Returns a pointer to the Unknown
//
//--------------------------------------------------------------------------
LPUNKNOWN CAMCView::GetPaneUnknown(ViewPane ePane)
{
TRACE_METHOD(CAMCView, GetPaneUnknown);
ASSERT_VALID(this);
if (!IsValidPane (ePane))
{
ASSERT (false && "CAMCView::GetPaneUnknown: Invalid pane specifier");
return (NULL);
}
if (!IsWindow (GetPaneView(ePane)->GetSafeHwnd()))
{
ASSERT(FALSE); // Invalid pane element
return NULL;
}
if (HasWebBrowser() && m_pWebViewCtrl != NULL)
{
return m_pWebViewCtrl->GetIUnknown();
}
else if( HasList() && m_pListCtrl != NULL )
{
IUnknownPtr spUnk = m_pListCtrl;
LPUNKNOWN pUnk = spUnk;
return pUnk;
}
else if (HasOCX() && m_pOCXHostView != NULL)
{
ASSERT(GetPaneView (ePane));
return m_pOCXHostView->GetIUnknown();
}
else
{
// result pane not initialized yet. This is usually because we are in between a deselect and a
// subsequent reselect.
return NULL;
}
}
//+-------------------------------------------------------------------------
//
// Function: SetPane
//
// Synopsis: Set a CWnd pointer for a particular pane and other information
//
//--------------------------------------------------------------------------
void CAMCView::SetPane(ViewPane ePane, CView* pView, EUIStyleType nStyle)
{
TRACE_METHOD(CAMCView, SetPane);
ASSERT_VALID(this);
if (!IsValidPane (ePane))
{
ASSERT (false && "CAMCView::SetPane: Invalid pane specifier");
return;
}
if (pView==NULL || !IsWindow(*pView))
{
ASSERT(FALSE); // Invalid arg
return;
}
m_PaneInfo[ePane].pView = pView;
// Ensure that the window is visible & at the top of the Z-order.
pView->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
// Note: We are directly showing the window for cases that controls
// don't show during a DoVerb(OLEIVERB_SHOW). Actually, this does a
// show on all windows. It's too hard at this point to optimize the code
// for doing this with an OLE control only.
::ShowWindow(pView->m_hWnd, SW_SHOW);
}
//
// Other Methods
//
/*+-------------------------------------------------------------------------*
* CAMCView::ScShowScopePane
*
* Shows or hides the scope pane in the current view. If fForce is true,
* we'll go through the motions of showing the scope pane even if we think
* its visibility state wouldn't change.
*--------------------------------------------------------------------------*/
SC CAMCView::ScShowScopePane (bool fShow, bool fForce /* =false */)
{
DECLARE_SC (sc, _T("CAMCView::ScShowScopePane"));
/*
* if the current visibility state doesn't match the requested state,
* change the current state to match the requested state
*/
if (fForce || (IsScopePaneVisible() != fShow))
{
/*
* If MMC_NW_OPTION_NOSCOPEPANE was specified when this view was
* created, we can't display a scope pane. If we're asked to, fail.
*/
if (fShow && !IsScopePaneAllowed())
return (sc = E_FAIL);
/*
* if the scope pane is being hidden and it contained the active
* view, activate the result pane
*/
if (!fShow && (GetFocusedPane() == ePane_ScopeTree))
ScSetFocusToResultPane (); // ignore errors here
/*
* remember the new state
*/
SetScopePaneVisible (fShow);
/*
* Don't defer this layout. This may be called by the Customize View
* dialog which wants to see its updates in real time. It will be
* sitting in a modal message loop so we won't get a chance to precess
* our idle task.
*/
RecalcLayout();
/*
* the console has changed
*/
SetDirty();
}
/*
* put the scope pane toolbar button in the right state
*/
CStandardToolbar* pStdToolbar = GetStdToolbar();
sc = ScCheckPointers(pStdToolbar, E_UNEXPECTED);
if (sc)
return (sc);
CAMCDoc *pDoc = GetDocument();
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
if (sc)
return sc;
bool bEnableScopePaneButton = (IsScopePaneAllowed() && pDoc->AllowViewCustomization());
// IF view customization is not allowed then "Show/Hide Consolte tree" button should be hidden.
if (bEnableScopePaneButton)
{
/*
* the scope pane is permitted; show and check the toolbar
* button if the scope pane is visible, show and uncheck the
* toolbar button if the scope pane is hidden
*/
sc = pStdToolbar->ScCheckScopePaneBtn (fShow);
if (sc)
return (sc);
}
else
{
/*
* no scope pane permitted, hide the scope pane button
*/
sc = pStdToolbar->ScEnableScopePaneBtn (bEnableScopePaneButton);
if (sc)
return (sc);
}
/*
* if we get to this point, the current state should match the requested state
*/
ASSERT (IsScopePaneVisible() == fShow);
return (sc);
}
/*+-------------------------------------------------------------------------*
* CAMCView::CDeferredLayout::CDeferredLayout
*
* Constructs a CAMCView::CDeferredLayout::CDeferredLayout. Note that if
* an error occurs during construction, an SC exception will be thrown.
*--------------------------------------------------------------------------*/
CAMCView::CDeferredLayout::CDeferredLayout (CAMCView* pAMCView)
: m_atomTask (AddAtom (_T("CAMCView::CDeferredLayout")))
{
DECLARE_SC (sc, _T("CAMCView::CDeferredLayout::CDeferredLayout"));
if (!Attach (pAMCView))
(sc = E_INVALIDARG).Throw();
}
/*+-------------------------------------------------------------------------*
* CAMCView::CDeferredLayout::~CDeferredLayout
*
*
*--------------------------------------------------------------------------*/
CAMCView::CDeferredLayout::~CDeferredLayout()
{
DeleteAtom (m_atomTask);
}
/*+-------------------------------------------------------------------------*
* CAMCView::CDeferredLayout::ScDoWork
*
*
*--------------------------------------------------------------------------*/
SC CAMCView::CDeferredLayout::ScDoWork()
{
WindowCollection::iterator it;
WindowCollection::iterator itEnd = m_WindowsToLayout.end();
for (it = m_WindowsToLayout.begin(); it != itEnd; ++it)
{
CWnd* pwnd = CWnd::FromHandlePermanent (*it);
CAMCView* pAMCView = dynamic_cast<CAMCView*>(pwnd);
if (pAMCView != NULL)
{
pAMCView->RecalcLayout();
pAMCView->Invalidate();
pAMCView->UpdateWindow();
}
}
return (S_OK);
}
/*+-------------------------------------------------------------------------*
* CAMCView::CDeferredLayout::ScGetTaskID
*
*
*--------------------------------------------------------------------------*/
SC CAMCView::CDeferredLayout::ScGetTaskID(ATOM* pID)
{
*pID = m_atomTask;
return (S_OK);
}
/*+-------------------------------------------------------------------------*
* CAMCView::CDeferredLayout::ScMerge
*
*
*--------------------------------------------------------------------------*/
SC CAMCView::CDeferredLayout::ScMerge(CIdleTask* pitMergeFrom)
{
CDeferredLayout* pdlMergeFrom = dynamic_cast<CDeferredLayout*>(pitMergeFrom);
ASSERT (pdlMergeFrom != NULL);
/*
* copy the windows from the merge-from task into the merge-to task
*/
WindowCollection::iterator it;
WindowCollection::iterator itEnd = pdlMergeFrom->m_WindowsToLayout.end();
for (it = pdlMergeFrom->m_WindowsToLayout.begin(); it != itEnd; ++it)
{
m_WindowsToLayout.insert (*it);
}
return (S_OK);
}
/*+-------------------------------------------------------------------------*
* CAMCView::CDeferredLayout::Attach
*
*
*--------------------------------------------------------------------------*/
bool CAMCView::CDeferredLayout::Attach (CAMCView* pAMCView)
{
ASSERT (pAMCView != NULL);
HWND hwndAMCView = pAMCView->GetSafeHwnd();
if (hwndAMCView != NULL)
m_WindowsToLayout.insert (hwndAMCView);
return (hwndAMCView != NULL);
}
/*+-------------------------------------------------------------------------*
* CAMCView::DeferRecalcLayout
*
*
*--------------------------------------------------------------------------*/
void CAMCView::DeferRecalcLayout (bool fUseIdleTaskQueue /* =true */, bool bArrangeIcons /* = false*/)
{
DECLARE_SC (sc, _T("CAMCView::DeferRecalcLayout"));
if (fUseIdleTaskQueue)
{
Trace (tagLayout, _T("CAMCView::DeferRecalcLayout (idle task)"));
try
{
/*
* get the idle task manager
*/
CIdleTaskQueue* pIdleTaskQueue = AMCGetIdleTaskQueue();
if (pIdleTaskQueue == NULL)
(sc = E_UNEXPECTED).Throw();
/*
* create the deferred layout task
*/
CAutoPtr<CDeferredLayout> spDeferredLayout (new CDeferredLayout (this));
if (spDeferredLayout == NULL)
(sc = E_OUTOFMEMORY).Throw();
/*
* put the task in the queue, which will take ownership of it
*/
sc = pIdleTaskQueue->ScPushTask (spDeferredLayout, ePriority_Normal);
if (sc)
sc.Throw();
/*
* if we get here, the idle task queue owns the idle task, so
* we can detach it from our smart pointer
*/
spDeferredLayout.Detach();
/*
* jiggle the message pump so that it wakes up and checks idle tasks
*/
PostMessage (WM_NULL);
}
catch (SC& scCaught)
{
/*
* if we failed to enqueue our deferred layout task, do the layout now
*/
RecalcLayout();
}
}
/*
* post a message instead of using the idle task queue
*/
else
{
/*
* we only need to post a message if there's not one in the queue
* already
*/
MSG msg;
if (!PeekMessage (&msg, GetSafeHwnd(),
m_nDeferRecalcLayoutMsg,
m_nDeferRecalcLayoutMsg,
PM_NOREMOVE))
{
PostMessage (m_nDeferRecalcLayoutMsg, bArrangeIcons);
Trace (tagLayout, _T("CAMCView::DeferRecalcLayout (posted message)"));
}
else
{
Trace (tagLayout, _T("CAMCView::DeferRecalcLayout (skipping redundant posted message)"));
}
}
}
//+-------------------------------------------------------------------------
//
// Function: RecalcLayout
//
// Synopsis: Calls methods to layout control and paint borders and splitters.
//
//--------------------------------------------------------------------------
void CAMCView::RecalcLayout(void)
{
TRACE_METHOD(CAMCView, RecalcLayout);
ASSERT_VALID(this);
Trace (tagLayout, _T("CAMCView::RecalcLayout"));
/*
* short out if the client rect is empty
*/
CRect rectClient;
GetClientRect (rectClient);
if (rectClient.IsRectEmpty())
return;
CDeferWindowPos dwp (10);
LayoutScopePane (dwp, rectClient);
LayoutResultPane (dwp, rectClient);
/*
* CDeferWindowPos dtor will position the windows
*/
}
/*+-------------------------------------------------------------------------*
* CAMCView::LayoutScopePane
*
*
*--------------------------------------------------------------------------*/
void CAMCView::LayoutScopePane (CDeferWindowPos& dwp, CRect& rectRemaining)
{
int cxScope = 0;
// If a scope pane is visible
if (IsScopePaneVisible())
{
int cxTotal = rectRemaining.Width();
// get the current width
cxScope = m_PaneInfo[ePane_ScopeTree].cx;
// if not determined yet, set scope pane width to 1/4 of window
if (cxScope == -1)
cxScope = cxTotal / 3;
/*
* Bug 86718: Make sure we leave at least the minimum width
* for the result pane, which is always visible
*/
cxScope = std::_MIN (cxScope, cxTotal - m_PaneInfo[ePane_Results].cxMin - m_cxSplitter);
/*
* remember the scope pane width
*/
m_PaneInfo[ePane_ScopeTree].cx = cxScope;
}
CRect rectScope = rectRemaining;
rectScope.right = rectScope.left + cxScope;
/*
* remove space used by the scope pane
* (and splitter) from the remaining area
*/
if (IsScopePaneVisible())
{
m_rectVSplitter.left = rectScope.right;
m_rectVSplitter.top = rectScope.top;
m_rectVSplitter.right = rectScope.right + m_cxSplitter;
m_rectVSplitter.bottom = rectScope.bottom;
rectRemaining.left = m_rectVSplitter.right;
/*
* Inflate the splitter rect to give a little bigger hot area.
* We need to do this logically instead of physically (i.e. instead
* of increasing m_cxSplitter) to keep the visuals right.
*/
m_rectVSplitter.InflateRect (GetSystemMetrics (SM_CXEDGE), 0);
}
else
m_rectVSplitter = g_rectEmpty;
/*
* scope pane
*/
dwp.AddWindow (GetPaneView(ePane_ScopeTree), rectScope,
SWP_NOZORDER | SWP_NOACTIVATE |
(IsScopePaneVisible() ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
}
/*+-------------------------------------------------------------------------*
* CAMCView::LayoutResultPane
*
* Lays out the children of the result pane.
*--------------------------------------------------------------------------*/
void CAMCView::LayoutResultPane (CDeferWindowPos& dwp, CRect& rectRemaining)
{
/*
* Note: the order of these calls to LayoutXxx is *critical*.
*/
LayoutResultDescriptionBar (dwp, rectRemaining);
LayoutResultFolderTabView (dwp, rectRemaining);
m_rectResultFrame = rectRemaining;
LayoutResultView (dwp, rectRemaining);
/*
* remember the final width of the result pane in m_PaneInfo[ePane_Results].cx
*/
m_PaneInfo[ePane_Results].cx = m_rectResultFrame.Width();
}
/*+-------------------------------------------------------------------------*
* CAMCView::LayoutResultFolderTabView
*
*
*--------------------------------------------------------------------------*/
void CAMCView::LayoutResultFolderTabView (CDeferWindowPos& dwp, CRect& rectRemaining)
{
DECLARE_SC(sc, TEXT("CAMCView::LayoutResultFolderTabView"));
sc = ScCheckPointers(m_pResultFolderTabView, E_UNEXPECTED);
if (sc)
return;
// layout the folder tab control - always on top.
bool bVisible = AreTaskpadTabsAllowed() && m_pResultFolderTabView->IsVisible();
CRect rectFolder;
if (bVisible)
m_pResultFolderTabView->Layout(rectRemaining, rectFolder);
else
rectFolder = g_rectEmpty;
DWORD dwPosFlags = SWP_NOZORDER | SWP_NOACTIVATE |
(bVisible ? SWP_SHOWWINDOW : SWP_HIDEWINDOW);
dwp.AddWindow (m_pResultFolderTabView, rectFolder, dwPosFlags);
}
/*+-------------------------------------------------------------------------*
* CAMCView::LayoutResultDescriptionBar
*
*
*--------------------------------------------------------------------------*/
void CAMCView::LayoutResultDescriptionBar (CDeferWindowPos& dwp, CRect& rectRemaining)
{
DWORD dwPosFlags = SWP_NOZORDER | SWP_NOACTIVATE;
CRect rectT = rectRemaining;
if (IsDescBarVisible() && !rectT.IsRectEmpty())
{
rectT.bottom = rectT.top + m_RightDescCtrl.GetHeight();
rectRemaining.top = rectT.bottom;
dwPosFlags |= SWP_SHOWWINDOW;
}
else
{
dwPosFlags |= SWP_HIDEWINDOW;
}
dwp.AddWindow (&m_RightDescCtrl, rectT, dwPosFlags);
}
/*+-------------------------------------------------------------------------*
* CAMCView::LayoutResultView
*
*
*--------------------------------------------------------------------------*/
void CAMCView::LayoutResultView (CDeferWindowPos& dwp, const CRect& rectRemaining)
{
DECLARE_SC (sc, _T("CAMCView::LayoutResultView"));
Trace (tagLayout, _T("CAMCView::LayoutResultView"));
CWnd* pwndResult = GetPaneView(ePane_Results);
/*
* we should never think the view is extended if we don't also have
* a view extension web host control
*/
ASSERT (!(m_fViewExtended && (m_pViewExtensionCtrl == NULL)));
/*
* if it exists, the view extension control is always at the bottom of
* the Z-order, and visible if the view is being extended
*/
if(m_pViewExtensionCtrl != NULL)
{
/*
* note no SWP_NOZORDER
*/
DWORD dwPosFlags = SWP_NOACTIVATE | ((m_fViewExtended)
? SWP_SHOWWINDOW
: SWP_HIDEWINDOW);
dwp.AddWindow (m_pViewExtensionCtrl, rectRemaining,
dwPosFlags, &CWnd::wndBottom);
}
/*
* If the view's not extended, show or hide the result window based on
* whether there's any room left in the positioning rectangle. (If the
* view is extended, the result window will have been hidden when the
* view extension was applied (in ScApplyViewExtension), and possibly
* redisplayed by the extension in ScSetViewExtensionFrame.)
*/
if (!m_fViewExtended)
{
DWORD dwFlags = SWP_NOZORDER | SWP_NOACTIVATE |
(rectRemaining.IsRectEmpty() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW);
dwp.AddWindow (pwndResult, rectRemaining, dwFlags);
}
/*
* lists in extended views and listpads don't get a border, all others do
*/
if (HasListOrListPad())
{
if (HasListPad())
{
sc = ScCheckPointers (m_pListCtrl, E_UNEXPECTED);
if (sc)
return;
CWnd* pwndListCtrl = m_pListCtrl->GetListViewPtr();
sc = ScCheckPointers (pwndListCtrl, E_UNEXPECTED);
if (sc)
return;
pwndListCtrl->ModifyStyleEx (WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED); // remove border
}
else if (m_fViewExtended)
pwndResult->ModifyStyleEx (WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED); // remove border
else
pwndResult->ModifyStyleEx (0, WS_EX_CLIENTEDGE, SWP_FRAMECHANGED); // add border
}
}
//
// Tracking and and hit testing methods
//
//+-------------------------------------------------------------------------
//
// Function: HitTestPane
//
// Synopsis: Test which pane contains the point arg, or ePane_None for
// the splitter bar
//
//--------------------------------------------------------------------------
int CAMCView::HitTestPane(CPoint& point)
{
TRACE_METHOD(CAMCView, HitTestPane);
if (PtInWindow(m_pTreeCtrl, point))
return ePane_ScopeTree;
if (m_PaneInfo[ePane_Results].pView &&
PtInWindow(m_PaneInfo[ePane_Results].pView, point))
return ePane_Results;
return ePane_None;
}
HNODE CAMCView::GetSelectedNode(void)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
TRACE_METHOD(CAMCView, GetSelectedNode);
// When the tree is empty we don't want to AV
HTREEITEM hti = m_pTreeCtrl->GetSelectedItem();
if (hti == NULL)
return NULL;
HNODE hNode = m_pTreeCtrl->GetItemNode(hti);
return hNode;
}
HNODE CAMCView::GetRootNode(void)
{
TRACE_METHOD(CAMCView, GetSelectedNode);
// When the tree is empty we don't want to AV
HTREEITEM hti = m_pTreeCtrl->GetRootItem();
if (hti == NULL)
return NULL;
HNODE hNode = m_pTreeCtrl->GetItemNode(hti);
return hNode;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScUpdateWindowTitle
*
* PURPOSE: Updates the window title and informs observers about the change.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScUpdateWindowTitle()
{
DECLARE_SC(sc, TEXT("CAMCView::ScUpdateWindowTitle"));
CChildFrame* pFrame = GetParentFrame();
sc = ScCheckPointers(pFrame);
if(sc)
return sc;
if (pFrame)
pFrame->OnUpdateFrameTitle(TRUE);
sc = ScFireEvent(CAMCViewObserver::ScOnViewTitleChanged, this);
return sc;
}
BOOL CAMCView::RenameItem(HNODE hNode, BOOL bScopeItem, MMC_COOKIE lResultItemCookie,
LPWSTR pszText, LRESULT* pResult)
{
DECLARE_SC(sc, TEXT("CAMCView::RenameItem"));
sc = S_FALSE;
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = bScopeItem;
selInfo.m_lCookie = lResultItemCookie;
if (pszText != NULL)
{
USES_CONVERSION;
/*
* Bug 322184: The snap-in may throw up some UI on this notification.
* The list or tree may have captured the mouse to look for a drag,
* which will interfere with the snap-in's UI. Release the capture
* during the callback and put it back when we're done.
*/
HWND hwndCapture = ::SetCapture (NULL);
sc = m_spNodeCallback->Notify(hNode, NCLBK_RENAME,
reinterpret_cast<LPARAM>(&selInfo), reinterpret_cast<LPARAM>(pszText));
/*
* put the capture back
*/
::SetCapture (hwndCapture);
}
*pResult = (sc == SC(S_OK));
if (*pResult)
{
sc = ScUpdateWindowTitle();
if(sc)
sc.TraceAndClear();
}
return TRUE;
}
BOOL CAMCView::DispatchListCtrlNotificationMsg(LPARAM lParam, LRESULT* pResult)
{
DECLARE_SC(sc, TEXT("CAMCView::DispatchListCtrlNotificationMsg"));
TRACE_METHOD(CAMCView, DispatchListCtrlNotificationMsg);
NM_LISTVIEW *pNm = reinterpret_cast<NM_LISTVIEW*>(lParam);
BOOL bReturn = TRUE;
switch (pNm->hdr.code)
{
case NM_RCLICK:
bReturn = FALSE; // In case of right click send the select notification to the snapin
// but return FALSE so that message is further processed to display
// context menu.
// Fall thro into NM_CLICK
case NM_CLICK:
{
sc = ScOnLeftOrRightMouseClickInListView();
if (sc)
return bReturn;
}
break;
case NM_DBLCLK:
OnListCtrlItemDblClk();
break;
case NM_CUSTOMDRAW:
*pResult = m_pListCtrl->OnCustomDraw (
reinterpret_cast<NMLVCUSTOMDRAW *>(lParam));
break;
case LVN_BEGINLABELEDITA:
case LVN_BEGINLABELEDITW:
{
CMainFrame* pFrame = AMCGetMainWnd();
if ((pFrame != NULL) && (IsVerbEnabled(MMC_VERB_RENAME) ||
m_bRenameListPadItem == true))
{
pFrame->SetInRenameMode(true);
return FALSE;
}
else
{
return TRUE;
}
break;
}
case LVN_ENDLABELEDITW:
case LVN_ENDLABELEDITA:
{
CMainFrame* pFrame = AMCGetMainWnd();
if (pFrame != NULL)
pFrame->SetInRenameMode(false);
LPARAM lResultParam = 0;
long index = -1;
LPWSTR pszText = NULL;
if (pNm->hdr.code == LVN_ENDLABELEDITW)
{
LV_DISPINFOW* pdi = (LV_DISPINFOW*) lParam;
index = pdi->item.iItem;
pszText = pdi->item.pszText;
lResultParam = pdi->item.lParam;
}
else // if (pNm->hdr.code == LVN_ENDLABELEDIT)
{
LV_DISPINFO* pdi = (LV_DISPINFO*) lParam;
index = pdi->item.iItem;
USES_CONVERSION;
pszText = T2W(pdi->item.pszText);
lResultParam = pdi->item.lParam;
}
if (IsVirtualList())
{
// for virtual list pass the item index rather than the lparam
HNODE hNodeSel = GetSelectedNode();
RenameItem(hNodeSel, FALSE, index, pszText, pResult);
}
else
{
CResultItem* pri = CResultItem::FromHandle (lResultParam);
if (pri != NULL)
{
if (pri->IsScopeItem())
RenameItem(pri->GetScopeNode(), TRUE, 0, pszText, pResult);
else
RenameItem(GetSelectedNode(), FALSE, pri->GetSnapinData(), pszText, pResult);
}
}
break;
}
case LVN_GETDISPINFOW:
{
LV_DISPINFOW *pDispInfo = reinterpret_cast<LV_DISPINFOW*>(lParam);
// If column is hidden do not forward the call to snapin.
if (m_pListCtrl && m_pListCtrl->IsColumnHidden(pDispInfo->item.iSubItem))
break;
m_spNodeCallback->GetDispInfo (GetSelectedNode(), &pDispInfo->item);
break;
}
case LVN_GETDISPINFOA:
{
LV_DISPINFOA *pDispInfo = reinterpret_cast<LV_DISPINFOA*>(lParam);
ASSERT (pDispInfo != NULL);
// If column is hidden do not forward the call to snapin.
if (m_pListCtrl && m_pListCtrl->IsColumnHidden(pDispInfo->item.iSubItem))
break;
/*
* put the data in the UNICODE structure for the query
*/
LV_ITEMW lviW;
lviW.mask = pDispInfo->item.mask;
lviW.iItem = pDispInfo->item.iItem;
lviW.iSubItem = pDispInfo->item.iSubItem;
lviW.state = pDispInfo->item.state;
lviW.stateMask = pDispInfo->item.stateMask;
lviW.cchTextMax = pDispInfo->item.cchTextMax;
lviW.iImage = pDispInfo->item.iImage;
lviW.lParam = pDispInfo->item.lParam;
lviW.iIndent = pDispInfo->item.iIndent;
if (pDispInfo->item.mask & LVIF_TEXT)
lviW.pszText = new WCHAR[pDispInfo->item.cchTextMax];
/*
* convert to ANSI
*/
if (SUCCEEDED (m_spNodeCallback->GetDispInfo (GetSelectedNode(), &lviW)) &&
(pDispInfo->item.mask & LVIF_TEXT))
{
WideCharToMultiByte (CP_ACP, 0, lviW.pszText, -1,
pDispInfo->item.pszText,
pDispInfo->item.cchTextMax,
NULL, NULL);
}
if (pDispInfo->item.mask & LVIF_TEXT)
delete [] lviW.pszText;
/*
* copy the results back to the ANSI structure
*/
pDispInfo->item.mask = lviW.mask;
pDispInfo->item.iItem = lviW.iItem;
pDispInfo->item.iSubItem = lviW.iSubItem;
pDispInfo->item.state = lviW.state;
pDispInfo->item.stateMask = lviW.stateMask;
pDispInfo->item.cchTextMax = lviW.cchTextMax;
pDispInfo->item.iImage = lviW.iImage;
pDispInfo->item.lParam = lviW.lParam;
pDispInfo->item.iIndent = lviW.iIndent;
break;
}
case LVN_DELETEALLITEMS:
// return TRUE to prevent notification for each item
return TRUE;
case LVN_ITEMCHANGED:
bReturn = OnListItemChanged (pNm);
break;
case LVN_ODSTATECHANGED:
// The state of an item or range of items has changed in virtual list.
return OnVirtualListItemsStateChanged(reinterpret_cast<LPNMLVODSTATECHANGE>(lParam));
break;
case LVN_ODFINDITEMA:
case LVN_ODFINDITEMW:
{
USES_CONVERSION;
NM_FINDITEM *pNmFind = reinterpret_cast<NM_FINDITEM*>(lParam);
ASSERT(IsVirtualList() && (pNmFind->lvfi.flags & LVFI_STRING));
LPOLESTR polestr = NULL;
if (pNm->hdr.code == LVN_ODFINDITEMW)
{
LVFINDINFOW* pfiw = reinterpret_cast<LVFINDINFOW*>(&pNmFind->lvfi);
polestr = const_cast<LPOLESTR>(pfiw->psz);
}
else
{
LVFINDINFOA* pfi = reinterpret_cast<LVFINDINFOA*>(&pNmFind->lvfi);
polestr = A2W(const_cast<LPSTR>(pfi->psz));
}
Dbg(DEB_USER1, _T("\n********************** polestr = %ws\n"), polestr);
RESULTFINDINFO findInfo;
findInfo.psz = polestr;
findInfo.nStart = pNmFind->iStart;
findInfo.dwOptions = 0;
// Listview bug: LVFI_SUBSTRING is not defined in the SDK headers and the
// listview sets it instead of LVFI_PARTIAL when it wants a
// partial match. So for now, define it here and test for both.
#define LVFI_SUBSTRING 0x0004
if (pNmFind->lvfi.flags & (LVFI_PARTIAL | LVFI_SUBSTRING))
findInfo.dwOptions |= RFI_PARTIAL;
if (pNmFind->lvfi.flags & LVFI_WRAP)
findInfo.dwOptions |= RFI_WRAP;
HNODE hNodeSel = GetSelectedNode();
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
pNC->Notify(hNodeSel, NCLBK_FINDITEM,
reinterpret_cast<LPARAM>(&findInfo),
reinterpret_cast<LPARAM>(pResult));
}
break;
case LVN_ODCACHEHINT:
{
NM_CACHEHINT *pNmHint = reinterpret_cast<NM_CACHEHINT*>(lParam);
ASSERT(IsVirtualList());
HNODE hNodeSel = GetSelectedNode();
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
pNC->Notify(hNodeSel, NCLBK_CACHEHINT, pNmHint->iFrom, pNmHint->iTo);
}
break;
case LVN_KEYDOWN:
{
NMLVKEYDOWN *pNmKeyDown = reinterpret_cast<NMLVKEYDOWN*>(lParam);
switch (pNmKeyDown->wVKey)
{
case VK_DELETE:
{
if (!IsVerbEnabled(MMC_VERB_DELETE))
break;
INodeCallback* pCallback = GetNodeCallback();
ASSERT(pCallback != NULL);
if (pCallback == NULL)
break;
HNODE hNode = GetSelectedNode();
if (hNode == 0)
break;
int cSel = m_pListCtrl->GetSelectedCount();
ASSERT(cSel >= 0);
LPARAM lvData;
if (cSel == 0)
{
break;
}
else if (cSel == 1)
{
if (_GetLVSelectedItemData(&lvData) == -1)
break;
}
else if (cSel > 1)
{
lvData = LVDATA_MULTISELECT;
}
else
{
break;
}
pCallback->Notify(hNode, NCLBK_DELETE, FALSE, lvData);
break;
}
break;
case VK_TAB:
GetParentFrame()->SetActiveView (m_pTreeCtrl);
break;
case VK_BACK:
ScUpOneLevel();
break;
case VK_RETURN:
if(GetKeyState(VK_MENU)<0) // has the ALT key been pressed?
{
// Process <ALT><ENTER>
if (! IsVerbEnabled(MMC_VERB_PROPERTIES))
break;
LPARAM lvData = 0;
if (HasList())
{
ASSERT (m_pListCtrl != NULL);
ASSERT (GetParentFrame()->GetActiveView() == m_pListCtrl->GetListViewPtr());
int cSel = m_pListCtrl->GetSelectedCount();
ASSERT(cSel >= 0);
lvData = LVDATA_ERROR;
if (cSel == 0)
lvData = LVDATA_BACKGROUND;
else if (cSel == 1)
_GetLVSelectedItemData(&lvData);
else if (cSel > 1)
lvData = LVDATA_MULTISELECT;
ASSERT(lvData != LVDATA_ERROR);
if (lvData == LVDATA_ERROR)
break;
if (lvData == LVDATA_BACKGROUND)
break;
}
else if (HasOCX())
{
lvData = LVDATA_CUSTOMOCX;
}
else
{
ASSERT(HasWebBrowser());
lvData = LVDATA_CUSTOMWEB;
}
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
if (pNC == NULL)
break;
HNODE hNodeSel = GetSelectedNode();
ASSERT(hNodeSel != NULL);
if (hNodeSel == NULL)
break;
pNC->Notify(hNodeSel, NCLBK_PROPERTIES, FALSE, lvData);
break;
}
else // nope, the ALT key has not been pressed.
{
// do the default verb.
OnListCtrlItemDblClk();
}
break;
default:
bReturn = OnSharedKeyDown(pNmKeyDown->wVKey);
break;
}
}
break;
default:
bReturn = FALSE;
break;
}
return bReturn;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScOnLeftOrRightMouseClickInListView
//
// Synopsis: Left or right mouse button is clicked on the list view, see
// if it is clicked on list-view background. If so send a select.
//
// Click on list view background is treated as scope owner item selected.
//
// Arguments: None
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScOnLeftOrRightMouseClickInListView()
{
DECLARE_SC(sc, TEXT("CAMCView::ScOnLeftOrRightMouseClickInListView"));
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
CAMCListView *pAMCListView = m_pListCtrl->GetListViewPtr();
sc = ScCheckPointers(pAMCListView, E_UNEXPECTED);
if (sc)
return sc;
CPoint pt;
GetCursorPos(&pt);
pAMCListView->ScreenToClient(&pt);
UINT uFlags = 0;
int iItem = pAMCListView->GetListCtrl().HitTest(pt, &uFlags);
Dbg(DEB_USER1, _T("----- HitTest > %d \n"), iItem);
// Make sure mouse click is in the ListView and there are
// no items selected in the list view.
if ( (iItem == -1) &&
!(uFlags & (LVHT_ABOVE | LVHT_BELOW | LVHT_TOLEFT | LVHT_TORIGHT) ) &&
(m_pListCtrl->GetSelectedCount() == 0) )
{
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(pNC, E_UNEXPECTED);
if (sc)
return sc;
HNODE hNodeSel = GetSelectedNode();
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = TRUE;
selInfo.m_bDueToFocusChange = TRUE;
selInfo.m_bBackground = TRUE;
selInfo.m_lCookie = LVDATA_BACKGROUND;
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, true, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
return (sc);
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnListItemChanged
*
* WM_NOTIFY (LVN_ITEMCHANGED) handler for CAMCView.
*
* return true as message is handled here.
*--------------------------------------------------------------------------*/
bool CAMCView::OnListItemChanged (NM_LISTVIEW* pnmlv)
{
DECLARE_SC (sc, _T("CAMCView::OnListItemChanged"));
bool bOldState = (pnmlv->uOldState & LVIS_SELECTED);
bool bNewState = (pnmlv->uNewState & LVIS_SELECTED);
// is this a selection change?
if ( (pnmlv->uChanged & LVIF_STATE) &&
(bOldState != bNewState) )
{
const int cSelectedItems = m_pListCtrl->GetSelectedCount();
#ifdef DBG
Trace (tagListSelection,
_T("Item %d %sselected, %d total items selected"),
pnmlv->iItem,
(pnmlv->uOldState & LVIS_SELECTED) ? _T("de") : _T(" "),
cSelectedItems);
#endif
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = FALSE;
selInfo.m_pView = NULL;
selInfo.m_lCookie = IsVirtualList() ? pnmlv->iItem : pnmlv->lParam;
/*
* If user is (de)selecting multiple items using control and/or shift keys
* then defer the multi-select notification until we're quiescent
* with the exception of only one item being (de)selected.
*/
if ((IsKeyPressed(VK_SHIFT) || IsKeyPressed(VK_CONTROL)) &&
(GetParentFrame()->GetActiveView() == m_pListCtrl->GetListViewPtr()) &&
(cSelectedItems > 1) )
{
// See ScPostMultiSelectionChangesMessage (this handles both selection
// and de-selection of multiple items).
sc = ScPostMultiSelectionChangesMessage();
if (sc)
sc.TraceAndClear();
return (true);
}
else
{
m_bProcessMultiSelectionChanges = false;
}
HNODE hNodeSel = GetSelectedNode();
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(pNC, (void*) hNodeSel, E_UNEXPECTED);
if (sc)
return (true);
// item = -1 is only expected for deselect in virtual list
ASSERT( pnmlv->iItem != -1 || (IsVirtualList() && (pnmlv->uOldState & LVIS_SELECTED)));
if (pnmlv->uOldState & LVIS_SELECTED)
{
if (cSelectedItems == 0)
{
if (!m_bLastSelWasMultiSel)
{
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, false, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
else
{
m_bLastSelWasMultiSel = false;
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
}
else if (m_bLastSelWasMultiSel)
{
// may need to cancel multiselect and send single select notify.
// if another change comes in, it will cancel the delayed message
// This fixes a problem that is caused by large icon mode not
// sending as many noifications as the other modes.
// See ScPostMultiSelectionChangesMessage (this handles both selection
// and de-selection of multiple items).
sc = ScPostMultiSelectionChangesMessage();
if (sc)
sc.TraceAndClear();
}
}
else if (pnmlv->uNewState & LVIS_SELECTED)
{
ASSERT(cSelectedItems >= 1);
if (cSelectedItems == 1)
{
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, true, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
else
{
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, true, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
m_bLastSelWasMultiSel = true;
}
}
}
return (true);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::OnVirtualListItemsStateChanged
//
// Synopsis: The state of an item or range of items has changed in virtual list.
//
// Arguments: lpStateChange -
//
// Returns: should return 0 according to docs.
//
//--------------------------------------------------------------------
int CAMCView::OnVirtualListItemsStateChanged(LPNMLVODSTATECHANGE lpStateChange )
{
DECLARE_SC(sc, TEXT("CAMCView::OnVirtualListItemsStateChanged"));
sc = ScCheckPointers(lpStateChange);
if (sc)
{
sc.TraceAndClear();
return 0;
}
bool bOldState = (lpStateChange->uOldState & LVIS_SELECTED);
bool bNewState = (lpStateChange->uNewState & LVIS_SELECTED);
int cItems = (lpStateChange->iTo - lpStateChange->iFrom) + 1;
#ifdef DBG
Trace (tagListSelection,
_T("Items %d to %d were %sselected, %d total items selected"),
lpStateChange->iFrom, lpStateChange->iTo,
bOldState ? _T("de") : _T(" "),
cItems );
#endif
if (bOldState != bNewState)
{
sc = ScPostMultiSelectionChangesMessage();
if (sc)
sc.TraceAndClear();
}
return (0);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScPostMultiSelectionChangesMessage
//
// Synopsis: Post selection change message (need to post because multi-sel
// may not be over, wait till it is quiet.)
//
// This method posts message telling selection states of multiple
// items are changed but not if they are selected or de-selected.
// The m_bLastSelWasMultiSel is used to determine if it is
// selection or de-selection.
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScPostMultiSelectionChangesMessage ()
{
DECLARE_SC(sc, _T("CAMCView::ScPostMultiSelectionChangesMessage"));
/*
* This is a multi-selection, defer notification until we're quiescent
*/
m_bProcessMultiSelectionChanges = true;
PostMessage (m_nProcessMultiSelectionChangesMsg);
// We need to disable all the toolbars, menubuttons
// during multiselect. Above PostMessage enables
// stdbar and MMC menubuttons.
CAMCViewToolbarsMgr* pAMCViewToolbarsMgr = m_ViewData.GetAMCViewToolbarsMgr();
CMenuButtonsMgr* pMenuBtnsMgr = m_ViewData.GetMenuButtonsMgr();
sc = ScCheckPointers(pAMCViewToolbarsMgr, pMenuBtnsMgr, E_UNEXPECTED);
if (sc)
return 0;
pAMCViewToolbarsMgr->ScDisableToolbars();
pMenuBtnsMgr->ScDisableMenuButtons();
return (sc);
}
void CAMCView::OpenResultItem(HNODE hNode)
{
/*
* Bug 139695: Make certain this function doesn't need to change the
* active view. We should only get here as a result of double- clicking
* or pressing Enter on a scope node in the result pane, in which case
* the result pane should already be the active view. If it is, we don't
* need to change the active view, which can cause the problems listed in
* the bug.
*/
ASSERT (m_pListCtrl != NULL);
ASSERT (GetParentFrame() != NULL);
ASSERT (GetParentFrame()->GetActiveView() == m_pListCtrl->GetListViewPtr());
ASSERT(m_pTreeCtrl);
HTREEITEM htiParent = m_pTreeCtrl->GetSelectedItem();
ASSERT(htiParent != NULL);
m_pTreeCtrl->ExpandNode(htiParent);
m_pTreeCtrl->Expand(htiParent, TVE_EXPAND);
HTREEITEM hti = m_pTreeCtrl->GetChildItem(htiParent);
if (hti == NULL)
return;
while (hti)
{
if (m_pTreeCtrl->GetItemNode(hti) == hNode)
break;
hti = m_pTreeCtrl->GetNextItem(hti, TVGN_NEXT);
}
if (hti != 0)
{
m_pTreeCtrl->Expand(htiParent, TVE_EXPAND);
m_pTreeCtrl->SelectItem(hti);
}
}
BOOL CAMCView::OnListCtrlItemDblClk(void)
{
TRACE_METHOD(CAMCView, OnListCtrlItemDblClk);
LPARAM lvData = -1;
if (_GetLVSelectedItemData(&lvData) == -1)
lvData = LVDATA_BACKGROUND;
HNODE hNodeSel = GetSelectedNode();
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
if (!pNC)
return FALSE;
HRESULT hr = pNC->Notify(hNodeSel, NCLBK_DBLCLICK, lvData, 0);
if (hr == S_FALSE)
{
ASSERT(lvData != LVDATA_BACKGROUND);
if (!IsVirtualList())
{
CResultItem* pri = CResultItem::FromHandle (lvData);
if ((pri != NULL) && pri->IsScopeItem())
OpenResultItem (pri->GetScopeNode());
}
}
return TRUE;
}
BOOL CAMCView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
DECLARE_SC(sc, TEXT("CAMCView::OnNotify"));
NMHDR *pNmHdr = reinterpret_cast<NMHDR*>(lParam);
sc = ScCheckPointers(pNmHdr, pResult);
if (sc)
{
sc.TraceAndClear();
return CView::OnNotify(wParam, lParam, pResult);
}
*pResult = TRUE; // init
switch(pNmHdr->code)
{
case HDN_ENDTRACKA: // Save the column width changes.
case HDN_ENDTRACKW: // HDN_BEGINTRACK handles dis-allowing hidden column dragging.
{
NMHEADER* nmh = (NMHEADER*)lParam;
CAMCListView *pAMCListView = m_pListCtrl->GetListViewPtr();
SC sc = ScCheckPointers(pAMCListView, E_UNEXPECTED);
if (sc)
{
sc.TraceAndClear();
return FALSE;
}
sc = pAMCListView->ScOnColumnsAttributeChanged(nmh, HDN_ENDTRACK);
if (sc)
{
sc.TraceAndClear();
return FALSE;
}
// S_FALSE : dont allow the change
if (sc == SC(S_FALSE))
return TRUE;
return CView::OnNotify(wParam, lParam, pResult);
}
break;
case HDN_ENDDRAG: // Column order changes.
{
NMHEADER* nmh = (NMHEADER*)lParam;
if (nmh->pitem->mask & HDI_ORDER)
{
CAMCListView *pAMCListView = m_pListCtrl->GetListViewPtr();
SC sc = ScCheckPointers(pAMCListView, E_UNEXPECTED);
if (sc)
{
sc.TraceAndClear();
return FALSE;
}
sc = pAMCListView->ScOnColumnsAttributeChanged(nmh, HDN_ENDDRAG);
if (sc)
{
sc.TraceAndClear();
return FALSE;
}
// S_FALSE : dont allow the change
if (sc = SC(S_FALSE))
return TRUE;
}
return CView::OnNotify(wParam, lParam, pResult);
}
break;
case TVN_BEGINLABELEDIT:
{
TV_DISPINFO* ptvdi = (TV_DISPINFO*)lParam;
if ((ptvdi->item.lParam == CAMCTreeView::LParamFromNode (GetSelectedNode())) &&
(IsVerbEnabled(MMC_VERB_RENAME) == FALSE))
{
return TRUE;
}
CMainFrame* pFrame = AMCGetMainWnd();
if (pFrame != NULL)
pFrame->SetInRenameMode(true);
return FALSE;
}
case TVN_ENDLABELEDIT:
{
TV_DISPINFO* ptvdi = (TV_DISPINFO*)lParam;
CMainFrame* pFrame = AMCGetMainWnd();
if (pFrame != NULL)
pFrame->SetInRenameMode(false);
USES_CONVERSION;
return RenameItem(CAMCTreeView::NodeFromLParam (ptvdi->item.lParam), TRUE, 0,
T2W(ptvdi->item.pszText), pResult);
}
case TVN_KEYDOWN:
{
TV_KEYDOWN* ptvkd = reinterpret_cast<TV_KEYDOWN*>(lParam);
if (ptvkd->wVKey == VK_TAB)
{
ScSetFocusToResultPane();
return TRUE;
}
else
{
return OnSharedKeyDown(ptvkd->wVKey);
}
}
}
if (UsingDefColumns() &&
(pNmHdr->code == HDN_ENDTRACKA || pNmHdr->code == HDN_ENDTRACKW))
{
// WARNING: If HD_NOTIFY::pitem::pszText needs to be used you should cast
// lParam to either HD_NOTIFYA or HD_NOTIFYW depending on the pNmHdr->code
HD_NOTIFY* phdn = reinterpret_cast<HD_NOTIFY*>(lParam);
ASSERT(phdn != NULL);
if (phdn->pitem->mask & HDI_WIDTH)
{
int alWidths[2] = {0, 0};
GetDefaultColumnWidths(alWidths);
alWidths[phdn->iItem] = phdn->pitem->cxy;
SetDefaultColumnWidths(alWidths, FALSE);
return TRUE;
}
}
#ifdef DBG
if (m_pTreeCtrl && m_pTreeCtrl->m_hWnd == pNmHdr->hwndFrom)
{
switch (pNmHdr->code)
{
case NM_CLICK: Dbg(DEB_USER2, "\t Tree item clicked\n"); break;
case NM_DBLCLK: Dbg(DEB_USER2, "\t Tree item dbl-clicked\n"); break;
case NM_RCLICK: Dbg(DEB_USER2, "\t Tree item R-clicked\n"); break;
default: break;
}
}
#endif
// HasList() is added to prevent dispatching notifications, when AMCView thinks
// it does not have a list. This lead to wrong assumptions about the list type
// and as a result - AV handling messages like GetDisplayInfo
// See BUG 451896
if (m_pListCtrl && HasListOrListPad())
{
if (m_pListCtrl->GetListViewHWND() == pNmHdr->hwndFrom)
{
if (DispatchListCtrlNotificationMsg(lParam, pResult) == TRUE)
return TRUE;
}
else if (m_pListCtrl->GetHeaderCtrl() && m_pListCtrl->GetHeaderCtrl()->m_hWnd == pNmHdr->hwndFrom)
{
switch(pNmHdr->code)
{
case HDN_ITEMCLICKA:
case HDN_ITEMCLICKW:
{
HNODE hNodeSel = GetSelectedNode();
HD_NOTIFY* phdn = reinterpret_cast<HD_NOTIFY*>(lParam);
ASSERT(phdn != NULL);
int nCol = phdn->iItem;
sc = m_spNodeCallback->Notify(hNodeSel, NCLBK_COLUMN_CLICKED, 0, nCol);
if (sc)
sc.TraceAndClear();
return TRUE;
}
// filter related code
case HDN_FILTERCHANGE:
{
HNODE hNodeSel = GetSelectedNode();
int nCol = ((NMHEADER*)lParam)->iItem;
sc = m_spNodeCallback->Notify(hNodeSel, NCLBK_FILTER_CHANGE, MFCC_VALUE_CHANGE, nCol);
if (sc)
sc.TraceAndClear();
return TRUE;
}
case HDN_FILTERBTNCLICK:
{
HNODE hNodeSel = GetSelectedNode();
int nCol = ((NMHDFILTERBTNCLICK*)lParam)->iItem;
RECT rc = ((NMHDFILTERBTNCLICK*)lParam)->rc;
// rect is relative to owning list box, convert to screen
::MapWindowPoints(m_pListCtrl->GetListViewHWND(), NULL, (LPPOINT)&rc, 2);
sc = m_spNodeCallback->Notify(hNodeSel, NCLBK_FILTERBTN_CLICK, nCol, (LPARAM)&rc);
*pResult = (sc == SC(S_OK));
if (sc)
sc.TraceAndClear();
return TRUE;
}
}
}
}
return CView::OnNotify(wParam, lParam, pResult);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnMinimize
*
* PURPOSE: Send the NCLBK_MINIMIZED notification to the node manager.
*
* PARAMETERS:
* bool fMinimized : TRUE if the window is being minimized, false if maximized.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnMinimize(bool fMinimized)
{
DECLARE_SC(sc, TEXT("CAMCView::ScOnMinimize"));
HNODE hNode = GetSelectedNode();
if (hNode == NULL)
return (sc = E_FAIL);
INodeCallback* pNodeCallback = GetNodeCallback();
if (pNodeCallback == NULL)
return (sc = E_FAIL);
sc = pNodeCallback->Notify (hNode, NCLBK_MINIMIZED, fMinimized, 0);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnSize
*
* PURPOSE: Send the size notification to all
*
* PARAMETERS:
* UINT nType :
* int cx :
* int cy :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnSize(UINT nType, int cx, int cy)
{
DECLARE_SC(sc, TEXT("CAMCView::ScOnSize"));
if (IsPersisted() && GetDocument())
GetDocument()->SetFrameModifiedFlag(true);
sc = ScFireEvent(CAMCViewObserver::ScOnViewResized, this, nType, cx, cy);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScActivate
*
* PURPOSE: Sets the view as the active view.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScActivate()
{
DECLARE_SC(sc, TEXT("CAMCView::ScActivate"));
// get the child frame.
CChildFrame * pChildFrame = GetParentFrame();
sc = ScCheckPointers(pChildFrame);
if(sc)
return sc;
if (pChildFrame->IsIconic())
pChildFrame->MDIRestore();
else
pChildFrame->MDIActivate(); // activate the child frame.
return sc;
}
void CAMCView::OnContextMenu(CWnd* pWnd, CPoint point)
{
TRACE_METHOD(CAMCView, OnContextMenu);
/*
* make sure this child frame is active
*/
GetParentFrame()->MDIActivate();
if (NULL == m_pTreeCtrl)
{
TRACE(_T("CAMCView::OnContextMenu: tree control not ready\n" ));
return;
}
// (-1,-1) => came from context menu key or Shift-F10
// Pop-up context for whatever has focus
if (point.x == -1 && point.y == -1)
{
OnShiftF10();
return;
}
switch (HitTestPane(point))
{
case ePane_Results:
{
CPoint pointListCtrlCoord = point;
CListView* pListView = m_pListCtrl->GetListViewPtr();
pListView->ScreenToClient(&pointListCtrlCoord);
CWnd* pwndHit = pListView->ChildWindowFromPoint (pointListCtrlCoord,
CWP_SKIPINVISIBLE);
/*
* if the hit window isn't the list view, it must be the list's
* header window; ignore the context menu request
*/
if (pwndHit != pListView)
{
TRACE (_T("CAMCView::OnContextMenu: ignore right-click on result pane header\n"));
break;
}
if (NULL != m_pListCtrl && pWnd->m_hWnd == m_pListCtrl->GetListViewHWND())
OnListContextMenu(point);
else
TRACE(_T("CAMCView::OnContextMenu: result control not ready\n"));
// CODEWORK should do something here
break;
}
case ePane_ScopeTree:
{
TRACE(_T("CAMCView::OnContextMenu: handle right-click on scope pane\n"));
CPoint pointTreeCtrlCoord = point;
m_pTreeCtrl->ScreenToClient(&pointTreeCtrlCoord);
OnTreeContextMenu( point, pointTreeCtrlCoord, NULL );
break;
}
case ePane_Tasks:
// TO BE ADDED - put up taskpad context menu
break;
case ePane_None:
TRACE(_T("CAMCView::OnContextMenu: ignore right-click on splitter\n"));
break;
default:
TRACE(_T("CAMCView::OnContextMenu: unexpected return value from HitTestPane()\n"));
ASSERT(FALSE);
}
}
void CAMCView::OnTreeContextMenu(CPoint& point, CPoint& pointClientCoord, HTREEITEM htiRClicked)
{
TRACE_METHOD(CAMCView, OnTreeContextMenu);
if (NULL == m_pTreeCtrl)
{
TRACE(_T("CAMCTreeView::OnTreeContextMenu: IFrame not ready\n"));
return;
}
UINT fHitTestFlags = TVHT_ONITEM;
if (htiRClicked == NULL)
htiRClicked = m_pTreeCtrl->HitTest(pointClientCoord, &fHitTestFlags);
switch(fHitTestFlags)
{
case TVHT_ABOVE:
case TVHT_BELOW:
case TVHT_TOLEFT:
case TVHT_TORIGHT:
// Outside the tree view area so return without doing anything.
return;
default:
break;
}
if (NULL == htiRClicked || !(fHitTestFlags & TVHT_ONITEM))
{
OnContextMenuForTreeBackground(point);
}
else
{
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(htiRClicked);
ASSERT(hNode != 0);
OnContextMenuForTreeItem(INDEX_INVALID, hNode, point, CCT_SCOPE, htiRClicked);
}
}
void CAMCView::OnContextMenuForTreeItem(int iIndex, HNODE hNode,
CPoint& point, DATA_OBJECT_TYPES type_of_pane,
HTREEITEM htiRClicked, MMC_CONTEXT_MENU_TYPES eMenuType,
LPCRECT prcExclude, bool bAllowDefaultItem)
{
TRACE_METHOD(CAMCView, OnContextMenuForTreeItem);
DECLARE_SC (sc, _T("CAMCView::OnContextMenuForTreeItem"));
ASSERT(hNode != 0);
CContextMenuInfo contextInfo;
contextInfo.m_displayPoint.x = point.x;
contextInfo.m_displayPoint.y = point.y;
contextInfo.m_eContextMenuType = eMenuType;
contextInfo.m_eDataObjectType = CCT_SCOPE;
contextInfo.m_bBackground = FALSE;
contextInfo.m_bScopeAllowed = IsScopePaneAllowed();
contextInfo.m_hWnd = m_hWnd;
contextInfo.m_pConsoleView = this;
contextInfo.m_bAllowDefaultItem = bAllowDefaultItem;
contextInfo.m_hSelectedScopeNode = GetSelectedNode();
contextInfo.m_htiRClicked = htiRClicked;
contextInfo.m_iListItemIndex = iIndex;
/*
* if given, initialize the rectangle not to obscure
*/
if (prcExclude != NULL)
contextInfo.m_rectExclude = *prcExclude;
// If selected scope node is same as node for which context menu is
// needed, then add savelist, view menus
if (contextInfo.m_hSelectedScopeNode == hNode)
{
// Show view owner items
contextInfo.m_dwFlags |= CMINFO_SHOW_VIEWOWNER_ITEMS;
// Don't need to remove temporary selection, since none was applied
contextInfo.m_pConsoleTree = NULL;
if (eMenuType == MMC_CONTEXT_MENU_DEFAULT)
contextInfo.m_dwFlags |= CMINFO_SHOW_VIEW_ITEMS;
if (HasListOrListPad())
contextInfo.m_dwFlags |= CMINFO_SHOW_SAVE_LIST;
}
else if (htiRClicked) // htiRClicked is NULL for tree items in list view.
{
// TempNodeSelect == TRUE -> menu is not for the node that owns the result pane
sc = m_pTreeCtrl->ScSetTempSelection (htiRClicked);
if (sc)
return;
contextInfo.m_pConsoleTree = m_pTreeCtrl;
contextInfo.m_dwFlags |= CMINFO_USE_TEMP_VERB;
}
if (htiRClicked)
contextInfo.m_dwFlags |= CMINFO_DO_SCOPEPANE_MENU;
else
contextInfo.m_dwFlags |= CMINFO_SCOPEITEM_IN_RES_PANE;
if (HasListOrListPad())
contextInfo.m_spListView = m_pListCtrl;
INodeCallback* spNodeCallback = GetNodeCallback();
ASSERT(spNodeCallback != NULL);
HRESULT hr = spNodeCallback->Notify(hNode, NCLBK_CONTEXTMENU, 0,
reinterpret_cast<LPARAM>(&contextInfo));
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::GetTaskpadID
*
* PURPOSE: returns the GUID id of the currently selected taskpad.
*
* RETURNS:
* GUID : the taskpad, if any, else GUID_NULL.
*
*+-------------------------------------------------------------------------*/
void
CAMCView::GetTaskpadID(GUID &guidID)
{
ITaskCallback * pTaskCallback = m_ViewData.m_spTaskCallback;
if(pTaskCallback != NULL)
{
pTaskCallback->GetTaskpadID(&guidID);
}
else
{
guidID = GUID_NULL;
}
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScInitializeMemento
*
* PURPOSE: Initializes the memento from the current view.
*
* PARAMETERS:
* CMemento & memento :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScInitializeMemento(CMemento &memento)
{
DECLARE_SC(sc, TEXT("CAMCView::ScInitializeMemento"));
sc = GetSelectedNodePath(&memento.GetBookmark());
if (sc)
return sc;
GUID guidTaskpad = GUID_NULL;
HNODE hNode = GetSelectedNode();
// get Result pane stuff from snapin
CResultViewType rvt;
sc = GetNodeCallback()->GetResultPane(hNode, rvt, &guidTaskpad /*this is not used*/);
if (sc)
return sc;
CViewSettings& viewSettings = memento.GetViewSettings();
// Initialize the CViewSettings.
sc = viewSettings.ScSetResultViewType(rvt);
if (sc)
return sc;
GUID guid;
GetTaskpadID(guid); // we use this guid instead of guidTaskpad because
// the memento should contain the taskpad that is currently being displayed.
sc = viewSettings.ScSetTaskpadID(guid);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::OnAddToFavorites
*
* PURPOSE: Creates a memento from the currently configured view. Saves it into a
* shortcut.
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void CAMCView::OnAddToFavorites()
{
DECLARE_SC(sc , _T("CAMCView::OnAddToFavorites"));
USES_CONVERSION;
CAMCDoc* pDoc = GetDocument();
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
if (sc)
return;
IScopeTree* const pScopeTree = GetScopeTreePtr();
sc = ScCheckPointers(pScopeTree, E_UNEXPECTED);
if (sc)
return;
CMemento memento;
sc = ScInitializeMemento(memento); // init the memento with the current view settings.
if(sc)
return;
HNODE hNode = GetSelectedNode();
tstring strName;
sc = GetNodeCallback()->GetDisplayName(hNode, strName);
if (sc)
return;
HMTNODE hmtNode;
sc = m_spNodeCallback->GetMTNode(hNode, &hmtNode);
if (sc)
return;
CCoTaskMemPtr<WCHAR> spszPath;
sc = pScopeTree->GetPathString(NULL, hmtNode, &spszPath);
if (sc)
return;
sc = ScCheckPointers(pDoc->GetFavorites(), E_UNEXPECTED);
if (sc)
return;
sc = pDoc->GetFavorites()->AddToFavorites(strName.data(), W2CT(spszPath), memento, this);
if (sc)
return;
pDoc->SetModifiedFlag();
}
void CAMCView::OnContextMenuForTreeBackground(CPoint& point, LPCRECT prcExclude, bool bAllowDefaultItem)
{
TRACE_METHOD(CAMCView, OnContextMenuForTreeBackground);
HNODE hNode = NULL;
CContextMenuInfo contextInfo;
contextInfo.m_displayPoint.x = point.x;
contextInfo.m_displayPoint.y = point.y;
contextInfo.m_eDataObjectType = CCT_SCOPE;
contextInfo.m_bBackground = TRUE;
contextInfo.m_bScopeAllowed = IsScopePaneAllowed();
contextInfo.m_hWnd = m_hWnd;
contextInfo.m_pConsoleView = this;
contextInfo.m_bAllowDefaultItem = bAllowDefaultItem;
/*
* if given, initialize the rectangle not to obscure
*/
if (prcExclude != NULL)
contextInfo.m_rectExclude = *prcExclude;
INodeCallback* spNodeCallback = GetNodeCallback();
ASSERT(spNodeCallback != NULL);
HRESULT hr = spNodeCallback->Notify(hNode, NCLBK_CONTEXTMENU, 0,
reinterpret_cast<LPARAM>(&contextInfo));
}
SC CAMCView::ScWebCommand (WebCommand eCommand)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
if (m_pWebViewCtrl == NULL)
{
ASSERT (m_pHistoryList);
if (!m_pHistoryList)
return FALSE;
// this is the case when we don't have a web control yet....
bool bHandled = false;
switch (eCommand)
{
case eWeb_Back:
m_pHistoryList->Back (bHandled);
ASSERT(bHandled);
break;
case eWeb_Forward:
m_pHistoryList->Forward (bHandled);
ASSERT(bHandled);
break;
default:
return FALSE;
}
return TRUE;
}
switch (eCommand)
{
case eWeb_Back: m_pWebViewCtrl->Back(); break;
case eWeb_Forward: m_pWebViewCtrl->Forward(); break;
case eWeb_Home: ASSERT(0 && "Should not come here! - remove all code related to Web_Home"); break;
case eWeb_Refresh: m_pWebViewCtrl->Refresh(); break;
case eWeb_Stop: m_pWebViewCtrl->Stop(); break;
default: ASSERT(0); return FALSE;
}
return TRUE;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScCreateTaskpadHost
*
* PURPOSE: Creates a legacy (snapin taskpad) host interface pointer
*
* NOTE: When a view containing a taskpad is navigated away from, the amcview
* forgets about the taskpad host pointer, but the html window does not.
* When the same view is re-navigated to using History, the amcview needs
* a taskpad host pointer, so a new instance is created. Thus at this point
* the amcview and the HTML have pointers to different taskpad host
* objects. This is OK, because both objects are initialized to the same
* amcview, and contain no other state
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScCreateTaskpadHost()
{
DECLARE_SC(sc , _T("CAMCView::ScCreateTaskpadHost"));
if(m_spTaskPadHost != NULL)
return sc;
CComObject<CTaskPadHost>* pTaskPadHost = NULL;
sc = CComObject<CTaskPadHost>::CreateInstance(&pTaskPadHost);
if (sc)
return sc;
sc = ScCheckPointers (pTaskPadHost, E_UNEXPECTED);
if (sc)
return sc;
pTaskPadHost->Init (this);
m_spTaskPadHost = pTaskPadHost;
return sc;
}
LRESULT CAMCView::OnConnectToCIC (WPARAM wParam, LPARAM lParam)
{
DECLARE_SC (sc, _T("CAMCView::OnConnectToCIC"));
// fill out wparam, which is an IUnknown ** (alloc'd by CIC)
ASSERT (wParam != NULL);
IUnknown ** ppunk = (IUnknown **)wParam;
ASSERT (!IsBadReadPtr (ppunk, sizeof(IUnknown *)));
ASSERT (!IsBadWritePtr (ppunk, sizeof(IUnknown *)));
sc = ScCheckPointers (ppunk);
if (sc)
return (sc.ToHr());
// lParam holds MMCCtrl's IUnknown: we can hang onto this if we
// need it. Presently not saved or used.
sc = ScCreateTaskpadHost();
if(sc)
return sc.ToHr();
sc = ScCheckPointers(m_spTaskPadHost, E_UNEXPECTED);
if(sc)
return sc.ToHr();;
sc = m_spTaskPadHost->QueryInterface(IID_IUnknown, (void **)ppunk);
if (sc)
return (sc.ToHr());
return (sc.ToHr());
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::OnGetIconInfoForSelectedNode
//
// Synopsis: Icon control sends this message to get the small icon
// for currently the selected node.
//
// Arguments: [wParam] - Out param, ptr to HICON handle.
// [lParam] - Unused
//
// Returns: LRESULT
//
//--------------------------------------------------------------------
LRESULT CAMCView::OnGetIconInfoForSelectedNode(WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC(sc, _T("CAMCView::OnGetIconInfoForSelectedNode"));
HICON *phIcon = (HICON*)wParam;
sc = ScCheckPointers(phIcon);
if (sc)
return sc.ToHr();
*phIcon = NULL;
sc = ScCheckPointers(m_pTreeCtrl, m_spNodeCallback, E_UNEXPECTED);
if (sc)
return sc.ToHr();
sc = m_pTreeCtrl->ScGetTreeItemIconInfo(GetSelectedNode(), phIcon);
return sc.ToHr();
}
HRESULT CAMCView::NotifyListPad (BOOL b)
{
if (b == TRUE) // attaching: save current node
m_ListPadNode = GetSelectedNode();
else if (m_ListPadNode == NULL) // detaching, but no hnode
return E_UNEXPECTED;
// send notify to snapin
INodeCallback* pNC = GetNodeCallback();
HRESULT hr = pNC->Notify (m_ListPadNode, NCLBK_LISTPAD, (long)b, (long)0);
if (b == FALSE) // if detaching, ensure that we do this only once
m_ListPadNode = NULL;
return hr;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnConnectToTPLV
*
* PURPOSE: Connects the listpad to the HTML frame
*
* PARAMETERS:
* WPARAM wParam : parent window
* LPARAM lParam : [OUT]: pointer to window to be created and filled out
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnConnectToTPLV(WPARAM wParam, LPARAM lParam)
{
DECLARE_SC(sc, _T("CAMCView::ScOnConnectToTPLV"));
HWND hwnd = (HWND )wParam;
if(!IsWindow (hwnd))
return (sc = S_FALSE);
if (lParam == NULL) // detaching
{
SC sc = m_pListCtrl->ScAttachToListPad (hwnd, NULL);
if(sc)
return sc;
}
else
{ // attaching
sc = ScCreateTaskpadHost();
if(sc)
return sc;
HWND* phwnd = (HWND*)lParam;
if (IsBadWritePtr (phwnd, sizeof(HWND *)))
return (sc = E_UNEXPECTED);
// Attach TaskPad's ListView to the NodeMgr
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if(sc)
return sc;
sc = m_pTreeCtrl->m_spNodeManager->SetTaskPadList(m_pListCtrl);
if(sc)
return sc;
// Attach TaskPad's ListView to the curr selected node
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(pNC, E_UNEXPECTED);
if(sc)
return sc;
HNODE hNodeSel = GetSelectedNode();
sc = pNC->SetTaskPadList(hNodeSel, m_pListCtrl);
if(sc) // this test was commented out earlier. Uncommented it so we can figure out why.
return sc;
//
// Attach the listctrl to the list pad.
//
// First set the list view options.
SetListViewOptions(GetListOptions());
sc = m_pListCtrl->ScAttachToListPad (hwnd, phwnd);
if(sc)
return sc;
}
RecalcLayout();
return sc;
}
SC CAMCView::ScShowWebContextMenu ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
PostMessage (m_nShowWebContextMenuMsg);
return (S_OK);
}
LRESULT CAMCView::OnShowWebContextMenu (WPARAM /*wParam*/, LPARAM /*lParam*/)
{
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
if (pNC)
pNC->Notify (GetSelectedNode(), NCLBK_WEBCONTEXTMENU, 0, 0);
return (0);
}
SC CAMCView::ScSetDescriptionBarText (LPCTSTR pszDescriptionText)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
GetRightDescCtrl().SetSnapinText (pszDescriptionText);
return (S_OK);
}
HWND CAMCView::CreateFavoriteObserver (HWND hwndParent, int nID)
{
DECLARE_SC (sc, _T("CAMCView::CreateFavoriteObserver"));
AFX_MANAGE_STATE (AfxGetAppModuleState());
CFavTreeCtrl* pFavCtrl = CFavTreeCtrl::CreateInstance();
if (pFavCtrl != NULL)
{
pFavCtrl->Create (NULL, TEXT(""), WS_CHILD|WS_TABSTOP|WS_VISIBLE,
g_rectEmpty, CWnd::FromHandle(hwndParent), nID);
pFavCtrl->ModifyStyleEx (0, WS_EX_CLIENTEDGE, 0);
CAMCDoc* pDoc = GetDocument();
ASSERT(pDoc != NULL && pDoc->GetFavorites() != NULL);
sc = pFavCtrl->ScInitialize(pDoc->GetFavorites(), TOBSRV_HIDEROOT);
if (sc)
{
pFavCtrl->DestroyWindow(); // CFavTreeCtrl::PostNcDestroy will "delete this"
pFavCtrl = NULL;
}
}
return (pFavCtrl->GetSafeHwnd());
}
int CAMCView::GetListSize ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
return (m_pListCtrl->GetItemCount() * m_pListCtrl->GetColCount());
}
long CAMCView::GetListViewStyle()
{
DECLARE_SC(sc, _T("CAMCView::GetListViewStyle"));
sc = ScCheckPointers(m_pTreeCtrl, m_pTreeCtrl->m_spResultData, E_UNEXPECTED);
if (sc)
return 0;
if (HasList())
return 0;
long style = 0;
// First findout if the result view is properly
// set in the nodemgr by asking IFramePrivate.
IFramePrivatePtr spFrame = m_pTreeCtrl->m_spResultData;
sc = ScCheckPointers(spFrame, E_UNEXPECTED);
if (sc)
return 0;
BOOL bIsResultViewSet = FALSE;
sc = spFrame->IsResultViewSet(&bIsResultViewSet);
// The result view is set, clean it up.
if (bIsResultViewSet)
{
sc = m_pTreeCtrl->m_spResultData->GetListStyle(&style);
if (sc)
return 0;
}
return style;
}
void CAMCView::OnListContextMenu(CPoint& point)
{
DECLARE_SC(sc, TEXT("CAMCView::OnListContextMenu"));
ASSERT(m_pTreeCtrl != NULL);
ASSERT(m_pTreeCtrl->m_spResultData != NULL);
// Determine which item is affected
UINT fHitTestFlags = 0;
HRESULTITEM hHitTestItem = 0;
COMPONENTID componentID = 0;
int iIndex = -1;
do // not a loop
{
if (!HasList())
break;
int cSel = m_pListCtrl->GetSelectedCount();
ASSERT(cSel >= 0);
if (cSel == 0)
{
OnContextMenuForListItem(INDEX_BACKGROUND, NULL, point);
return;
}
else if (cSel > 1)
{
if (IsKeyPressed(VK_SHIFT) || IsKeyPressed(VK_CONTROL))
{
HNODE hNodeSel = GetSelectedNode();
ASSERT(hNodeSel != 0);
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
if (pNC != NULL)
{
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, true, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
m_bLastSelWasMultiSel = true;
}
}
iIndex = INDEX_MULTISELECTION; // => MultiSelect
break;
}
else
{
LPARAM lvData = LVDATA_ERROR;
iIndex = _GetLVSelectedItemData(&lvData);
ASSERT(iIndex != -1);
ASSERT(lvData != LVDATA_ERROR);
if (IsVirtualList())
{
// for virtual list pass the item index rather than the lparam
OnContextMenuForListItem(iIndex, iIndex, point);
return;
}
else
{
CResultItem* pri = CResultItem::FromHandle (lvData);
if (pri != NULL)
{
if (pri->IsScopeItem())
OnContextMenuForTreeItem(iIndex, pri->GetScopeNode(), point, CCT_SCOPE);
else
OnContextMenuForListItem(iIndex, lvData, point);
}
return;
}
}
} while (0);
OnContextMenuForListItem(iIndex, hHitTestItem, point);
}
void CAMCView::OnContextMenuForListItem(int iIndex, HRESULTITEM hHitTestItem,
CPoint& point, MMC_CONTEXT_MENU_TYPES eMenuType,
LPCRECT prcExclude, bool bAllowDefaultItem)
{
CContextMenuInfo contextInfo;
contextInfo.m_displayPoint.x = point.x;
contextInfo.m_displayPoint.y = point.y;
contextInfo.m_eContextMenuType = eMenuType;
contextInfo.m_eDataObjectType = CCT_RESULT;
contextInfo.m_bBackground = (iIndex == INDEX_BACKGROUND);
contextInfo.m_bMultiSelect = (iIndex == INDEX_MULTISELECTION);
contextInfo.m_bAllowDefaultItem = bAllowDefaultItem;
if (iIndex >= 0)
contextInfo.m_resultItemParam = IsVirtualList() ? iIndex : hHitTestItem;
else if (contextInfo.m_bMultiSelect)
contextInfo.m_resultItemParam = LVDATA_MULTISELECT;
contextInfo.m_bScopeAllowed = IsScopePaneAllowed();
contextInfo.m_hWnd = m_hWnd;
contextInfo.m_pConsoleView = this;
contextInfo.m_hSelectedScopeNode = GetSelectedNode();
contextInfo.m_iListItemIndex = iIndex;
if (HasListOrListPad())
contextInfo.m_spListView = m_pListCtrl;
if ((INDEX_OCXPANE == iIndex) && HasOCX())
{
contextInfo.m_resultItemParam = LVDATA_CUSTOMOCX;
}
else if ((INDEX_WEBPANE == iIndex) && HasWebBrowser())
{
contextInfo.m_resultItemParam = LVDATA_CUSTOMWEB;
}
/*
* if given, initialize the rectangle not to obscure
*/
if (prcExclude != NULL)
contextInfo.m_rectExclude = *prcExclude;
HNODE hNode = GetSelectedNode();
ASSERT(hNode != NULL);
INodeCallback* pNodeCallback = GetNodeCallback();
ASSERT(pNodeCallback != NULL);
HRESULT hr = pNodeCallback->Notify(hNode, NCLBK_CONTEXTMENU, 0,
reinterpret_cast<LPARAM>(&contextInfo));
}
HTREEITEM CAMCView::FindChildNode(HTREEITEM hti, DWORD dwItemDataKey)
{
hti = m_pTreeCtrl->GetChildItem(hti);
while (hti && (dwItemDataKey != m_pTreeCtrl->GetItemData(hti)))
{
hti = m_pTreeCtrl->GetNextItem(hti, TVGN_NEXT);
}
return hti;
}
///////////////////////////////////////////////////////////////////////////////
/// Context Menu Handlers for Result View Item and Background
void CAMCView::ArrangeIcon(long style)
{
#ifdef OLD_STUFF
ASSERT(m_pTreeCtrl && m_pTreeCtrl->m_pNodeInstCurr);
if (!m_pTreeCtrl || !m_pTreeCtrl->m_pNodeInstCurr)
return;
IFrame* const pFrame = m_pTreeCtrl->m_pNodeInstCurr->GetIFrame();
ASSERT(pFrame);
if (!pFrame)
return;
IResultDataPrivatePtr pResult = pFrame;
ASSERT(static_cast<bool>(pResult));
if (pResult == NULL)
return ;
HRESULT hr = pResult->Arrange(style);
ASSERT(SUCCEEDED(style));
#endif // OLD_STUFF
}
///////////////////////////////////////////////////////////////////////////////
/// Menu handlers
CAMCView::ViewPane CAMCView::GetFocusedPane ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
ASSERT_VALID (this);
CView* pActiveView = GetParentFrame()->GetActiveView();
for (ViewPane ePane = ePane_First; ePane <= ePane_Last; ePane = (ViewPane)(ePane+1))
{
if (GetPaneView (ePane) == pActiveView)
return (ePane);
}
return (ePane_None);
}
/*+-------------------------------------------------------------------------*
* CDeferredResultPaneActivation
*
*
* PURPOSE: If the result pane has the focus before and after the node was
* selected, then the last event snapin receives is scope selected which
* is incorrect. So we first set scope pane as active view but do not
* send notifications. Then we set result pane as active view which
* sends scope de-select and result pane select.
* But when we try to set result pane as active view, the listview may
* not be visible yet (if there is view extension, the behavior hides
* and then shows the listview).
* So we need to wait till listview is setup. We cannot use PostMessage
* as the resizing of listview happens using PostMessage which is sent
* later (race condition). Therefore we use the idle timer as shown below
* so that activation will occur after resizing occurs.
*
*+-------------------------------------------------------------------------*/
class CDeferredResultPaneActivation : public CIdleTask
{
public:
CDeferredResultPaneActivation(HWND hWndAMCView) :
m_atomTask (AddAtom (_T("CDeferredResultPaneActivation"))),
m_hWndAMCView(hWndAMCView)
{
}
~CDeferredResultPaneActivation() {}
// IIdleTask methods
SC ScDoWork()
{
DECLARE_SC (sc, TEXT("CDeferredResultPaneActivation::ScDoWork"));
sc = ScCheckPointers((void*)m_hWndAMCView, E_UNEXPECTED);
if (sc)
return (sc);
CWnd *pWnd = CWnd::FromHandle(m_hWndAMCView);
sc = ScCheckPointers(pWnd, E_UNEXPECTED);
if (sc)
return sc;
CAMCView *pAMCView = dynamic_cast<CAMCView*>(pWnd);
// Since this method is called by IdleQueue, the target
// CAMCView may have gone by now, if it does not exist
// it is not an error (see bug 175737 related to SQL).
if (! pAMCView)
return sc;
sc = pAMCView->ScSetFocusToResultPane();
if (sc)
return sc;
return sc;
}
SC ScGetTaskID(ATOM* pID)
{
DECLARE_SC (sc, TEXT("CDeferredResultPaneActivation::ScGetTaskID"));
sc = ScCheckPointers(pID);
if(sc)
return sc;
*pID = m_atomTask;
return sc;
}
SC ScMerge(CIdleTask* pitMergeFrom) {return S_FALSE /*do not merge*/;}
private:
const ATOM m_atomTask;
HWND m_hWndAMCView;
};
/*+-------------------------------------------------------------------------*
* CAMCView::ScDeferSettingFocusToResultPane
*
* Synopsis: If the result pane has the focus before and after the node was
* selected, then the last event snapin receives is scope selected which
* is incorrect. So we first set scope pane as active view but do not
* send notifications. Then we set result pane as active view which
* sends scope de-select and result pane select.
* But when we try to set result pane as active view, the listview may
* not be visible yet (if there is view extension, the behavior hides
* and then shows the listview).
* So we need to wait till listview is setup. We cannot use PostMessage
* as the resizing of listview happens using PostMessage which is sent
* later (race condition). Therefore we use the idle timer as shown below
* so that activation will occur after resizing occurs.
*
* Returns: SC
*
*--------------------------------------------------------------------------*/
SC CAMCView::ScDeferSettingFocusToResultPane ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState()); // not sure if we need this, but doesn't hurt to have it in here.
DECLARE_SC (sc, TEXT("CAMCView::ScDeferSettingFocusToResultPane"));
CIdleTaskQueue* pIdleTaskQueue = AMCGetIdleTaskQueue();
sc = ScCheckPointers(pIdleTaskQueue, E_UNEXPECTED);
if(sc)
return sc;
/*
* create the deferred page break task
*/
CAutoPtr<CDeferredResultPaneActivation> spDeferredResultPaneActivation(new CDeferredResultPaneActivation (GetSafeHwnd()));
sc = ScCheckPointers(spDeferredResultPaneActivation, E_OUTOFMEMORY);
if(sc)
return sc;
/*
* put the task in the queue, which will take ownership of it
* Activation should happen at lower priority than layout.
*/
sc = pIdleTaskQueue->ScPushTask (spDeferredResultPaneActivation, ePriority_Low);
if (sc)
return sc;
/*
* if we get here, the idle task queue owns the idle task, so
* we can detach it from our smart pointer
*/
spDeferredResultPaneActivation.Detach();
/*
* jiggle the message pump so that it wakes up and checks idle tasks
*/
PostMessage (WM_NULL);
return (S_OK);
}
//+-------------------------------------------------------------------
//
// Member: ScSetFocusToResultPane
//
// Synopsis: Set focus to result pane (list or ocx or web). If result
// is hidden then set to folder tab else set to tasks pane.
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScSetFocusToResultPane ()
{
DECLARE_SC(sc, TEXT("CAMCView::ScSetFocusToResultPane"));
AFX_MANAGE_STATE (AfxGetAppModuleState());
if (GetFocusedPane() == ePane_Results)
return (sc);
// Make active
// 1. ListView/OCX/Web if it exists else
// 2. Folder tab if it exists.
// 3. Tasks in console taskpad.
CView* rgActivationOrderEntry[] =
{
GetPaneView(ePane_Results), // results
m_pResultFolderTabView, // result tab control
m_pViewExtensionCtrl, // view extension web page
};
const int INDEX_RESULTS_PANE = 0;
ASSERT (rgActivationOrderEntry[INDEX_RESULTS_PANE] == GetPaneView(ePane_Results));
int cEntries = (sizeof(rgActivationOrderEntry) / sizeof(rgActivationOrderEntry[0]));
// get the currently active entry.
for(int i = 0; i< cEntries; i++)
{
CView *pView = rgActivationOrderEntry[i];
sc = ScCheckPointers(pView, E_UNEXPECTED);
if (sc)
continue;
if (IsWindow (pView->GetSafeHwnd()) &&
pView->IsWindowVisible() &&
pView->IsWindowEnabled())
{
GetParentFrame()->SetActiveView (pView);
return (sc);
}
}
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: ScSetFocusToPane
//
// Synopsis: Call this member to set focus to any pane.
//
// Arguments:
//
// Returns:
//
//--------------------------------------------------------------------
SC CAMCView::ScSetFocusToPane (ViewPane ePane)
{
DECLARE_SC(sc, TEXT("CAMCView::ScSetFocusToPane"));
AFX_MANAGE_STATE (AfxGetAppModuleState());
if (!IsValidPane (ePane))
{
ASSERT (false && "CAMCView::ScSetFocusToPane: Invalid pane specifier");
return (sc = E_FAIL);
}
if (GetFocusedPane() == ePane)
return (sc);
if (ePane == ePane_Results)
return (sc = ScSetFocusToResultPane());
CView* pView = GetPaneView(ePane);
if (!IsWindow (pView->GetSafeHwnd()) ||
!pView->IsWindowVisible() ||
!pView->IsWindowEnabled())
{
return (sc = E_FAIL);
}
GetParentFrame()->SetActiveView (pView);
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScGetFocusedItem
//
// Synopsis: Get the currently selected item's context.
//
// Arguments: [hNode] - [out] The owner of result pane.
// [lCookie] - [out] If result pane selected the LVDATA.
// [fScope] - [out] scope or result
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScGetFocusedItem (HNODE& hNode, LPARAM& lCookie, bool& fScope)
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetFocusedItem"));
AFX_MANAGE_STATE (AfxGetAppModuleState());
ASSERT_VALID (this);
lCookie = LVDATA_ERROR;
hNode = GetSelectedNode();
if (hNode == NULL)
return (sc = E_UNEXPECTED);
switch (m_eCurrentActivePane)
{
case eActivePaneScope:
fScope = true;
break;
case eActivePaneResult:
{
fScope = false;
// Calculate the LPARAM for result item.
if (HasOCX())
lCookie = LVDATA_CUSTOMOCX;
else if (HasWebBrowser())
lCookie = LVDATA_CUSTOMWEB;
else if (HasListOrListPad())
{
int cSel = m_pListCtrl->GetSelectedCount();
ASSERT(cSel >= 0);
if (cSel == 0)
lCookie = LVDATA_BACKGROUND;
else if (cSel == 1)
_GetLVSelectedItemData (&lCookie);
else if (cSel > 1)
lCookie = LVDATA_MULTISELECT;
}
else
{
return (sc = E_FAIL); // dont know who has the focus???
}
}
break;
case eActivePaneNone:
default:
sc = E_UNEXPECTED;
break;
}
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::PrivateChangeListViewMode
//
// Synopsis: Private function to change view mode. Consider using
// ScChangeViewMode instead of this function.
//
// Arguments: [nMode] - view mode to be set.
//
//--------------------------------------------------------------------
void CAMCView::PrivateChangeListViewMode(int nMode)
{
DECLARE_SC(sc, TEXT("CAMCView::PrivateChangeListViewMode"));
if ((nMode < 0) || (nMode > MMCLV_VIEWSTYLE_FILTERED) )
{
sc = E_INVALIDARG;
return;
}
// Add a history entry which will be same as current
// one except for view mode change.
sc = ScCheckPointers(m_pHistoryList, m_pListCtrl, E_UNEXPECTED);
if (sc)
return;
// change the current history list entry's view mode
sc = m_pHistoryList->ScChangeViewMode(nMode);
if(sc)
return;
// set the list control's view mode
sc = m_pListCtrl->SetViewMode(nMode);
if (!sc)
{
m_nViewMode = nMode;
SetDirty();
SetDefaultListViewStyle(GetListViewStyle());
}
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::OnProcessMultiSelectionChanges
//
// Synopsis: message handler for m_nProcessMultiSelectionChangesMsg
// messages that are posted.
//
// Handles multi-item de-selection for list view and then
// send selection for list view items.
//
// This method knows that selection states of multiple items
// are changed but not if they are selected or de-selected.
// The m_bLastSelWasMultiSel is used to determine if it is
// selection or de-selection.
//
// Arguments: none used.
//
// Returns: LRESULT
//
//--------------------------------------------------------------------
LRESULT CAMCView::OnProcessMultiSelectionChanges (WPARAM, LPARAM)
{
DECLARE_SC(sc, _T("CAMCView::OnProcessMultiSelectionChanges"));
// Selection change so appropriately enable std-toolbar buttons
// back, forward, export-list, up-one-level, show/hide-scope, help
sc = ScUpdateStandardbarMMCButtons();
if (sc)
return (0);
if (! m_bProcessMultiSelectionChanges)
return (0);
m_bProcessMultiSelectionChanges = false;
INodeCallback* pNC = GetNodeCallback();
HNODE hNodeSel = GetSelectedNode();
sc = ScCheckPointers((void*) hNodeSel, pNC, m_pListCtrl, E_UNEXPECTED);
if (sc)
return (0);
// If some thing was selected previously send a deselection
// message before sending a selection message (single item de-select
// is already handled in OnListItemChanged so just handle multi item
// deselect here).
if (m_bLastSelWasMultiSel)
{
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
m_bLastSelWasMultiSel = false;
}
// Now send a selection message
UINT cSel = m_pListCtrl->GetSelectedCount ();
if (cSel == 1)
{
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = FALSE;
int iItem = _GetLVSelectedItemData(&selInfo.m_lCookie);
ASSERT(iItem != -1);
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, true, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
else if (cSel > 1)
{
Dbg(DEB_USER1, _T(" 5. LVN_SELCHANGE <MS> <0, 1>\n"));
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, true, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
m_bLastSelWasMultiSel = true;
}
return (0);
}
SC CAMCView::ScRenameListPadItem() // obsolete?
{
DECLARE_SC (sc, _T("CAMCView::ScRenameListPadItem"));
AFX_MANAGE_STATE (AfxGetAppModuleState());
ASSERT(m_pListCtrl != NULL);
ASSERT(m_pListCtrl->GetListViewPtr() != NULL);
int cSel = m_pListCtrl->GetSelectedCount();
if (cSel != 1)
return (sc = E_FAIL);
LPARAM lParam;
int iItem = _GetLVSelectedItemData(&lParam);
ASSERT(iItem >= 0);
if (iItem >= 0)
{
m_bRenameListPadItem = true;
m_pListCtrl->GetListViewPtr()->SetFocus();
m_pListCtrl->GetListViewPtr()->GetListCtrl().EditLabel(iItem);
m_bRenameListPadItem = false;
}
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOrganizeFavorites
*
* PURPOSE: Display the "organize favorites" dialog.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOrganizeFavorites()
{
DECLARE_SC (sc, TEXT("CAMCView::ScOrganizeFavorites"));
CAMCDoc* pDoc = GetDocument();
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
if(sc)
return sc;
CFavorites *pFavorites = pDoc->GetFavorites();
sc = ScCheckPointers(pFavorites);
if(sc)
return sc;
pFavorites->OrganizeFavorites(this);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScLineUpIcons
*
* PURPOSE: line up the icons in the list
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScLineUpIcons()
{
DECLARE_SC (sc, TEXT("CAMCView::ScLineUpIcons"));
ArrangeIcon(LVA_SNAPTOGRID);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScAutoArrangeIcons
*
* PURPOSE: auto arrange the icons in the list
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScAutoArrangeIcons()
{
DECLARE_SC(sc, TEXT("CAMCView::ScAutoArrangeIcons"));
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if(sc)
return sc;
m_pListCtrl->SetListStyle(m_pListCtrl->GetListStyle() ^ LVS_AUTOARRANGE);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnRefresh
*
* PURPOSE: Refreshes the view.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnRefresh(HNODE hNode, bool bScope, LPARAM lResultItemParam)
{
DECLARE_SC(sc, TEXT("CAMCView::ScOnRefresh"));
sc = ScCheckPointers((void*)hNode);
if (sc)
return sc;
HWND hwnd = ::GetFocus();
sc = ScProcessConsoleVerb(hNode, bScope, lResultItemParam, evRefresh);
::SetFocus(hwnd);
if (sc)
return sc;
return sc;
}
/***************************************************************************\
*
* CLASS: CDeferredRenameListItem
*
* PURPOSE: This class encapsulates means to put a list control in the rename mode
* asynchronously. This is needed to assure all mesages are processed before
* and no-one will steel the focus ending unexpectidly the edit mode.
*
* USAGE:
* use CDeferredRenameListItem::ScDoRenameAsIdleTask() to invoke the operation
* asyncronously
*
\***************************************************************************/
class CDeferredRenameListItem : public CIdleTask
{
// constructor - used internally only
CDeferredRenameListItem( HWND hwndListCtrl, int iItemIndex ) :
m_atomTask (AddAtom (_T("CDeferredRenameListItem"))),
m_hwndListCtrl(hwndListCtrl), m_iItemIndex(iItemIndex)
{
}
protected:
// IIdleTask methods
SC ScDoWork()
{
DECLARE_SC (sc, TEXT("CDeferredRenameListItem::ScDoWork"));
// get the ListCtrl pointer
CListCtrl *pListCtrl = (CListCtrl *)CWnd::FromHandlePermanent(m_hwndListCtrl);
sc = ScCheckPointers( pListCtrl );
if (sc)
return sc;
// do what you are asked for - put LV in the rename mode
pListCtrl->SetFocus(); // set the focus first. Don't need to do a SetActiveView here, I believe (vivekj)
pListCtrl->EditLabel( m_iItemIndex );
return sc;
}
SC ScGetTaskID(ATOM* pID)
{
DECLARE_SC (sc, TEXT("CDeferredPageBreak::ScGetTaskID"));
sc = ScCheckPointers(pID);
if(sc)
return sc;
*pID = m_atomTask;
return sc;
}
SC ScMerge(CIdleTask* pitMergeFrom) { return S_FALSE /*do not merge*/; }
public:
// this method is called to invoke rename asyncronously.
// it constructs the idle task and puts it into the queue
static SC ScDoRenameAsIdleTask( HWND hwndListCtrl, int iItemIndex )
{
DECLARE_SC(sc, TEXT("CDeferredPageBreak::ScDoRenameAsIdleTask"));
CIdleTaskQueue* pIdleTaskQueue = AMCGetIdleTaskQueue();
sc = ScCheckPointers(pIdleTaskQueue, E_UNEXPECTED);
if(sc)
return sc;
// create the deferred task
CAutoPtr<CDeferredRenameListItem> spTask(new CDeferredRenameListItem (hwndListCtrl, iItemIndex));
sc = ScCheckPointers( spTask, E_OUTOFMEMORY);
if(sc)
return sc;
// put the task in the queue, which will take ownership of it
sc = pIdleTaskQueue->ScPushTask (spTask, ePriority_Normal);
if (sc)
return sc;
// ownership tranfered to the queue, get rid of control over the pointer
spTask.Detach();
return sc;
}
private:
const ATOM m_atomTask;
HWND m_hwndListCtrl;
int m_iItemIndex;
};
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnRename
*
* PURPOSE: Allows the user to renames the scope or result item specified by pContextInfo
*
* PARAMETERS:
* CContextMenuInfo * pContextInfo :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnRename(CContextMenuInfo *pContextInfo)
{
DECLARE_SC(sc, TEXT("CAMCView::ScOnRename"));
sc = ScCheckPointers(pContextInfo, m_pTreeCtrl, m_pListCtrl);
if(sc)
return sc;
if (pContextInfo->m_htiRClicked != NULL)
{
m_pTreeCtrl->EditLabel(pContextInfo->m_htiRClicked);
}
else
{
ASSERT(pContextInfo->m_iListItemIndex >= 0);
sc = ScCheckPointers(m_pListCtrl->GetListCtrl());
if(sc)
return sc;
// Do this on idle - or else we'll suffer from someone steeling focus
// Syncronous operation fails in console task case.
sc = CDeferredRenameListItem::ScDoRenameAsIdleTask( m_pListCtrl->GetListCtrl().m_hWnd, pContextInfo->m_iListItemIndex );
if(sc)
return sc;
}
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScRenameScopeNode
*
* PURPOSE: put the specified scope node into rename mode.
*
* PARAMETERS:
* HMTNODE hMTNode : The scope node
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScRenameScopeNode(HMTNODE hMTNode)
{
DECLARE_SC(sc, TEXT("CAMCView::ScRenameScopeNode"));
sc = ScCheckPointers(m_pTreeCtrl, E_FAIL);
if(sc)
return sc;
sc = m_pTreeCtrl->ScRenameScopeNode(hMTNode);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetStatusBar
*
* PURPOSE: Returns the status bar
*
* PARAMETERS:
* CConsoleStatusBar ** ppStatusBar :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScGetStatusBar(CConsoleStatusBar **ppStatusBar)
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetStatusBar"));
sc = ScCheckPointers(ppStatusBar);
if(sc)
return sc;
*ppStatusBar = m_ViewData.GetStatusBar();
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetProperty
*
* PURPOSE: Gets the property for a result item
*
* PARAMETERS:
* int m_iIndex : The index of the item in the list.
* BSTR bstrPropertyName :
* PBSTR pbstrPropertyValue :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScGetProperty(int iIndex, BSTR bstrPropertyName, PBSTR pbstrPropertyValue)
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetProperty"));
sc = ScCheckPointers(GetNodeCallback(), m_pListCtrl, E_UNEXPECTED);
if(sc)
return sc;
LPARAM resultItemParam = iIndex; // the virtual list case
bool bScopeItem = false; // the virtual list case
if(!IsVirtualList())
{
CResultItem *pri = NULL;
sc = m_pListCtrl->GetLParam(iIndex, pri);
if(sc)
return sc;
resultItemParam = CResultItem::ToHandle(pri);
sc = ScCheckPointers(pri);
if(sc)
return sc;
bScopeItem = pri->IsScopeItem();
}
sc = GetNodeCallback()->GetProperty(GetSelectedNode(), bScopeItem, resultItemParam, bstrPropertyName, pbstrPropertyValue);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetNodetype
*
* PURPOSE: Returns the nodetype for a list item
*
* PARAMETERS:
* int iIndex :
* PBSTR Nodetype :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScGetNodetype(int iIndex, PBSTR Nodetype)
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetProperty"));
sc = ScCheckPointers(GetNodeCallback(), m_pListCtrl, E_UNEXPECTED);
if(sc)
return sc;
LPARAM resultItemParam = iIndex; // the virtual list case
bool bScopeItem = false; // the virtual list case
if(!IsVirtualList())
{
CResultItem *pri = NULL;
sc = m_pListCtrl->GetLParam(iIndex, pri);
if(sc)
return sc;
resultItemParam = CResultItem::ToHandle(pri);
sc = ScCheckPointers(pri);
if(sc)
return sc;
bScopeItem = pri->IsScopeItem();
}
sc = GetNodeCallback()->GetNodetypeForListItem(GetSelectedNode(), bScopeItem, resultItemParam, Nodetype);
return sc;
}
/*+-------------------------------------------------------------------------*
* CAMCView::ScAddViewExtension
*
*
*--------------------------------------------------------------------------*/
SC CAMCView::ScAddViewExtension (const CViewExtensionData& ved)
{
DECLARE_SC (sc, _T("CAMCView::ScAddViewExtension"));
return (sc);
}
void
CAMCView::OnChangedResultTab(NMHDR *nmhdr, LRESULT *pRes)
{
DECLARE_SC(sc, TEXT("CAMCView::OnChangedResultTab"));
NMFOLDERTAB* nmtab = static_cast<NMFOLDERTAB*>(nmhdr);
int iTab = nmtab->iItem;
CFolderTab &tab = m_pResultFolderTabView->GetItem(iTab);
GUID guidTaskpad = tab.GetClsid();
// check if we're moving to the same taskpad.
GUID guidCurrentTaskpad;
GetTaskpadID(guidCurrentTaskpad);
if(guidTaskpad == guidCurrentTaskpad)
return;
// lookup view extension URL
CViewExtensionURLs::iterator itVE = m_ViewExtensionURLs.find(guidTaskpad);
LPCTSTR url = (itVE != m_ViewExtensionURLs.end()) ? itVE->second.c_str() : NULL;
// apply URL
sc = ScApplyViewExtension(url);
if (sc)
sc.TraceAndClear();
GetNodeCallback()->SetTaskpad(GetSelectedNode(), &guidTaskpad); // if not found, guidTaskpad is set to GUID_NULL.
// After setting the taskpad enable/disable save list button
CStandardToolbar* pStdToolbar = GetStdToolbar();
ASSERT(NULL != pStdToolbar);
if (NULL != pStdToolbar)
{
pStdToolbar->ScEnableExportList(GetListSize() > 0 /*Enable only if LV has items*/);
}
// the taskpad changed. Create a new entry in the history list.
sc = m_pHistoryList->ScModifyViewTab( guidTaskpad );
if(sc)
sc.TraceAndClear();
}
HRESULT
CAMCView::GetRootNodePath(
CBookmark* pbm)
{
HTREEITEM htiRoot = m_pTreeCtrl->GetRootItem();
return GetNodePath(htiRoot, htiRoot, pbm);
}
HRESULT
CAMCView::GetSelectedNodePath(
CBookmark* pbm)
{
return GetNodePath(m_pTreeCtrl->GetSelectedItem(),
m_pTreeCtrl->GetRootItem(),
pbm);
}
HRESULT
CAMCView::GetNodePath(
HTREEITEM hti,
HTREEITEM htiRoot,
CBookmark* pbm)
{
TRACE_METHOD(CAMCView, GetRootNodeID);
if (hti == NULL)
return E_FAIL;
if (htiRoot == NULL)
return E_FAIL;
ASSERT(hti != NULL);
ASSERT(htiRoot != NULL);
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
HNODE hRootNode = (HNODE)m_pTreeCtrl->GetItemData(htiRoot);
HRESULT hr = m_spNodeCallback->GetPath(hNode, hRootNode, (LPBYTE) pbm);
return hr;
}
inline HMTNODE CAMCView::GetHMTNode(HTREEITEM hti)
{
TRACE_METHOD(CAMCView, GetHMTNode);
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
HMTNODE hMTNodeTemp;
HRESULT hr = m_spNodeCallback->GetMTNode(hNode, &hMTNodeTemp);
CHECK_HRESULT(hr);
return hMTNodeTemp;
}
HTREEITEM CAMCView::FindHTreeItem(HMTNODE hMTNode, HTREEITEM hti)
{
TRACE_METHOD(CAMCView, FindHTreeItem);
while (hti)
{
if (hMTNode == GetHMTNode(hti))
break;
hti = m_pTreeCtrl->GetNextItem(hti, TVGN_NEXT);
}
return hti;
}
UINT CAMCView::ClipPath(CHMTNODEList* pNodeList, POSITION& rpos, HNODE hNode)
{
TRACE_METHOD(CAMCView, ClipPath);
UINT uiReturn = ITEM_IS_IN_VIEW;
CCoTaskMemPtr<HMTNODE> sphMTNode;
long lLength = 0;
HRESULT hr = m_spNodeCallback->GetMTNodePath(hNode, &sphMTNode, &lLength);
CHECK_HRESULT(hr);
if (FAILED(hr))
return hr;
ASSERT(lLength == 0 || sphMTNode != NULL);
for (long i=0; rpos != 0 && i < lLength; i++)
{
HMTNODE hMTNode = pNodeList->GetNext(rpos);
if (hMTNode != sphMTNode[i])
{
uiReturn = ITEM_NOT_IN_VIEW;
break;
}
}
if (uiReturn == ITEM_NOT_IN_VIEW)
return ITEM_NOT_IN_VIEW;
return (rpos == 0 && lLength >= i) ? ITEM_IS_PARENT_OF_ROOT : ITEM_IS_IN_VIEW;
}
//
// GetTreeItem returns TRUE if it can find the htreeitem of the item
// whose HMTNode is equal to the last element in pNodeList. It returns
// FALSE if the node does not appear in the view name space or if the
// the node has not yet been created.
//
// "pNodeList" is a list of HMTNODEs such that pNodeList[n] is the parent
// of pNodeList[n+1].
//
UINT CAMCView::GetTreeItem(CHMTNODEList* pNodeList, HTREEITEM* phItem)
{
TRACE_METHOD(CAMCView, GetTreeItem);
ASSERT(pNodeList->IsEmpty() == FALSE);
HTREEITEM hti = NULL;
HMTNODE hMTNodeTemp = 0;
hti = m_pTreeCtrl->GetRootItem();
if (hti == NULL)
return ITEM_NOT_IN_VIEW;
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
POSITION pos = pNodeList->GetHeadPosition();
UINT uiReturn = ClipPath(pNodeList, pos, hNode);
if (uiReturn != ITEM_IS_IN_VIEW)
return uiReturn;
HTREEITEM htiTemp = NULL;
while (pos && hti)
{
hMTNodeTemp = (HMTNODE)pNodeList->GetNext(pos);
hti = FindHTreeItem(hMTNodeTemp, hti);
ASSERT(hti == NULL || hMTNodeTemp == GetHMTNode(hti));
htiTemp = hti;
if (hti != NULL)
hti = m_pTreeCtrl->GetChildItem(hti);
}
if (pos == 0 && htiTemp != NULL)
{
// Found the node.
ASSERT(hMTNodeTemp == pNodeList->GetTail());
ASSERT(hMTNodeTemp == GetHMTNode(htiTemp));
*phItem = htiTemp;
return ITEM_IS_IN_VIEW;
}
else
{
// The node has not yet been created.
*phItem = NULL;
return ITEM_NOT_IN_VIEW;
}
return ITEM_IS_IN_VIEW;
}
#define HMTNODE_FIRST reinterpret_cast<HMTNODE>(TVI_FIRST)
#define HMTNODE_LAST reinterpret_cast<HMTNODE>(TVI_LAST)
void CAMCView::OnAdd(SViewUpdateInfo *pvui)
{
TRACE_METHOD(CAMCView, OnAdd);
ASSERT(pvui->path.IsEmpty() == FALSE);
HTREEITEM htiParent;
if (GetTreeItem(&pvui->path, &htiParent) != ITEM_IS_IN_VIEW || htiParent == NULL)
return;
bool bFirstChild = (m_pTreeCtrl->GetChildItem(htiParent) == NULL);
HNODE hNodeParent = (HNODE)m_pTreeCtrl->GetItemData(htiParent);
if (m_spNodeCallback->Notify(hNodeParent, NCLBK_EXPAND, 0, 0) == S_FALSE)
{
m_pTreeCtrl->SetCountOfChildren(htiParent, 1);
return; // Don't add if it is not expanded.
}
// If the hNode was already expanded add the item.
IScopeTree* const pScopeTree = GetScopeTree();
ASSERT(pScopeTree != NULL);
HNODE hNodeNew = 0;
HRESULT hr = pScopeTree->CreateNode(pvui->newNode,
reinterpret_cast<LONG_PTR>(GetViewData()),
FALSE, &hNodeNew);
CHECK_HRESULT(hr);
if (FAILED(hr))
return;
HTREEITEM hInsertAfter = TVI_LAST;
int iInsertIndex = -1;
if (pvui->insertAfter != NULL)
{
hInsertAfter = reinterpret_cast<HTREEITEM>(pvui->insertAfter);
if (pvui->insertAfter == HMTNODE_LAST)
{
}
else if (pvui->insertAfter == HMTNODE_FIRST)
{
iInsertIndex = 0;
}
else
{
HTREEITEM hti = m_pTreeCtrl->GetChildItem(htiParent);
ASSERT(hti != NULL);
iInsertIndex = 1;
while (hti != NULL)
{
if (GetHMTNode(hti) == pvui->insertAfter)
break;
hti = m_pTreeCtrl->GetNextSiblingItem(hti);
iInsertIndex++;
}
if (hti)
{
hInsertAfter = hti;
}
else
{
hInsertAfter = TVI_LAST;
iInsertIndex = -1;
}
}
}
if (m_pTreeCtrl->InsertNode(htiParent, hNodeNew, hInsertAfter) == NULL)
return;
// if parent of the inserted item currently owns a non-virtual result list,
// add the item to result list too. Don't add the item if a node select is in
// progress because the tree control will automatically add all scope items
// as part of the select procedure.
if (OwnsResultList(htiParent) && CanInsertScopeItemInResultPane() )
{
// Ensure the node is enumerated
m_pTreeCtrl->ExpandNode(htiParent);
// Add to result pane.
RESULTDATAITEM tRDI;
::ZeroMemory(&tRDI, sizeof(tRDI));
tRDI.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
tRDI.nCol = 0;
tRDI.str = MMC_TEXTCALLBACK;
tRDI.nIndex = iInsertIndex;
int nImage;
int nSelectedImage;
hr = m_spNodeCallback->GetImages(hNodeNew, &nImage, &nSelectedImage);
ASSERT(hr == S_OK || nImage == 0);
tRDI.nImage = nImage;
tRDI.lParam = CAMCTreeView::LParamFromNode (hNodeNew);
LPRESULTDATA pResultData = m_pTreeCtrl->GetResultData();
ASSERT(pResultData != NULL);
hr = pResultData->InsertItem(&tRDI);
CHECK_HRESULT(hr);
if (SUCCEEDED(hr))
hr = m_spNodeCallback->SetResultItem(hNodeNew, tRDI.itemID);
}
if ((m_pTreeCtrl->GetRootItem() == htiParent) ||
((bFirstChild == true) &&
(m_spNodeCallback->Notify(hNodeParent, NCLBK_GETEXPANDEDVISUALLY, 0, 0) == S_OK)))
{
m_pTreeCtrl->Expand(htiParent, TVE_EXPAND);
}
}
void CAMCView::OnDeleteEmptyView()
{
if (m_pTreeCtrl->GetRootItem() == NULL)
{
++m_nReleaseViews;
if (m_nReleaseViews == 3)
{
// Ensure that there is at least one *persistable* view
CAMCDoc* pDoc = dynamic_cast<CAMCDoc*>(GetDocument());
ASSERT(pDoc != NULL);
int cViews = pDoc->GetNumberOfPersistedViews();
ASSERT(cViews >= 1);
if ((cViews == 1) && IsPersisted())
{
CMainFrame* pMain = dynamic_cast<CMainFrame*>(AfxGetMainWnd());
ASSERT(pMain != NULL);
if ( pMain != NULL )
pMain->SendMessage(WM_COMMAND, ID_WINDOW_NEW, 0);
}
DeleteView();
}
}
}
void CAMCView::OnDelete(SViewUpdateInfo *pvui)
{
TRACE_METHOD(CAMCView, OnDelete);
ASSERT(pvui->path.IsEmpty() == FALSE);
HTREEITEM hti;
UINT uiReturn = GetTreeItem(&pvui->path, &hti);
if (uiReturn == ITEM_NOT_IN_VIEW)
return;
ASSERT(uiReturn != ITEM_IS_IN_VIEW || pvui->path.GetTail() == GetHMTNode(hti));
HTREEITEM htiSel = m_pTreeCtrl->GetSelectedItem();
BOOL fDeleteThis = (pvui->flag & VUI_DELETE_THIS) ? TRUE : FALSE;
BOOL fExpandable = (pvui->flag & VUI_DELETE_SETAS_EXPANDABLE) ? TRUE : FALSE;
if (uiReturn == ITEM_IS_PARENT_OF_ROOT ||
NULL == hti)
{
hti = m_pTreeCtrl->GetRootItem();
fDeleteThis = TRUE;
fExpandable = FALSE;
}
ASSERT(hti != NULL);
// If deleted scope item is also shown in the result pane
// delete it there too. Can't happen with a virtual list.
// Don't try deleting item if selection is in progress because
// the scope items haven't been added yet.
if (fDeleteThis == TRUE &&
OwnsResultList(m_pTreeCtrl->GetParentItem(hti)) &&
CanInsertScopeItemInResultPane())
{
INodeCallback* pNC = GetNodeCallback();
HRESULTITEM itemID;
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
HRESULT hr = pNC->GetResultItem(hNode, &itemID);
if (SUCCEEDED(hr) && itemID != 0)
{
IResultData* pIRD = m_pTreeCtrl->GetResultData();
pIRD->DeleteItem(itemID, 0);
}
}
m_pTreeCtrl->DeleteNode(hti, fDeleteThis);
if (fDeleteThis == FALSE && fExpandable == TRUE)
m_pTreeCtrl->SetItemState(hti, 0, TVIS_EXPANDEDONCE | TVIS_EXPANDED);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::OnUpdateSelectionForDelete
*
* PURPOSE: Called when a scope node is deleted. If the node is an ancestor
* of the currently selected node, the selection is changed to the closest
* node of the deleted node. This is either the next sibling of the node that is being deleted,
* or, if there is no next sibling, the previous sibling, or, if there is none,
* the parent.
*
* PARAMETERS:
* SViewUpdateInfo* pvui :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CAMCView::OnUpdateSelectionForDelete(SViewUpdateInfo* pvui)
{
DECLARE_SC(sc, TEXT("CAMCView::OnUpdateSelectionForDelete"));
// make sure we have a path to the deleted node.
if(pvui->path.IsEmpty())
{
sc = E_UNEXPECTED;
return;
}
HTREEITEM htiToDelete;
UINT uiReturn = GetTreeItem(&pvui->path, &htiToDelete);
if (uiReturn == ITEM_IS_IN_VIEW && NULL != htiToDelete)
{
HTREEITEM htiSel = m_pTreeCtrl->GetSelectedItem();
BOOL fDeleteThis = (pvui->flag & VUI_DELETE_THIS);
// Determine whether the selected node is a descendant of the
// node bring deleted.
HTREEITEM htiTemp = htiSel;
while (htiTemp != NULL && htiTemp != htiToDelete)
{
htiTemp = m_pTreeCtrl->GetParentItem(htiTemp);
}
if (htiToDelete == htiTemp)
{
// The selected node is a descendant of the
// node being deleted.
if (fDeleteThis == TRUE)
htiTemp = m_pTreeCtrl->GetParentItem(htiToDelete);
if (!htiTemp)
htiTemp = htiToDelete;
if (htiTemp != htiSel)
{
HNODE hNode = m_pTreeCtrl->GetItemNode(htiSel);
m_pTreeCtrl->OnDeSelectNode(hNode);
ASSERT(htiTemp != NULL);
if (htiTemp != NULL)
m_pTreeCtrl->SelectItem(htiTemp);
}
}
}
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnUpdateTaskpadNavigation
*
* PURPOSE:
*
* PARAMETERS:
* SViewUpdateInfo * pvui:
*
* RETURNS:
* void
/*+-------------------------------------------------------------------------*/
void CAMCView::OnUpdateTaskpadNavigation(SViewUpdateInfo *pvui)
{
TRACE_METHOD(CAMCView, OnupdateTaskpadNavigation);
ASSERT(pvui->newNode != NULL);
//m_spNodeCallback->UpdateTaskpadNavigation(GetSelectedNode(), pvui->newNode);
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnModify
*
* PURPOSE:
*
* PARAMETERS:
* SViewUpdateInfo * pvui:
*
* RETURNS:
* void
/*+-------------------------------------------------------------------------*/
void CAMCView::OnModify(SViewUpdateInfo *pvui)
{
TRACE_METHOD(CAMCView, OnModify);
ASSERT(pvui->path.IsEmpty() == FALSE);
HNODE hNode = 0;
HTREEITEM hti;
if (GetTreeItem(&pvui->path, &hti) == ITEM_IS_IN_VIEW && hti != NULL)
{
ASSERT(m_pTreeCtrl != NULL);
m_pTreeCtrl->ResetNode(hti);
/*
* The name of the selected node and all of its ancestors are
* displayed in the frame title. If the modified item is an
* ancestor of the selected node, we need to update the frame title.
*/
HTREEITEM htiAncesctor;
for (htiAncesctor = m_pTreeCtrl->GetSelectedItem();
htiAncesctor != NULL;
htiAncesctor = m_pTreeCtrl->GetParentItem (htiAncesctor))
{
if (htiAncesctor == hti)
{
CChildFrame* pFrame = GetParentFrame();
if (pFrame)
pFrame->OnUpdateFrameTitle(TRUE);
break;
}
}
ASSERT(hti != NULL);
if (hti != NULL &&
OwnsResultList(m_pTreeCtrl->GetParentItem(hti)) &&
!IsVirtualList())
{
// Continue only if the currently selected item is the parent
// of the modified node. In this case we need to update the
// result view. Can't happen with a virtual list.
if (hNode == 0)
hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
ASSERT(hNode != NULL);
HRESULTITEM hri;
HRESULT hr = m_spNodeCallback->GetResultItem(hNode, &hri);
CHECK_HRESULT(hr);
// NOTE: the test for itemID != NULL below is related to bug 372242:
// MMC asserts on index server root node.
// What happens is that the snapin adds scope nodes on a SHOW event.
// These items have not yet been added to the result pane and so itemID
// comes back NULL.
if (SUCCEEDED(hr) && hri != NULL)
m_pListCtrl->OnModifyItem(CResultItem::FromHandle(hri));
}
}
}
void CAMCView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
Dbg(DEB_USER1, _T("CAMCView::OnUpdate<0x%08x, 0x%08x, 0x%08x>\n"),
pSender, lHint, pHint);
SViewUpdateInfo *pvui = reinterpret_cast<SViewUpdateInfo*>(pHint);
switch (lHint)
{
case 0:
// Sent by CView::OnInitialUpdate()
break;
case VIEW_UPDATE_ADD:
OnAdd(pvui);
break;
case VIEW_UPDATE_SELFORDELETE:
OnUpdateSelectionForDelete(pvui);
break;
case VIEW_UPDATE_DELETE:
OnDelete(pvui);
break;
case VIEW_UPDATE_DELETE_EMPTY_VIEW:
OnDeleteEmptyView();
break;
case VIEW_UPDATE_MODIFY:
OnModify(pvui);
break;
case VIEW_RESELECT:
if (m_ViewData.m_spControlbarsCache != NULL)
m_ViewData.m_spControlbarsCache->DetachControlbars();
m_pTreeCtrl->ScReselect();
break;
case VIEW_UPDATE_TASKPAD_NAVIGATION:
OnUpdateTaskpadNavigation(pvui);
break;
default:
ASSERT(0);
}
}
static int static_nViewID = 1;
UINT CAMCView::GetViewID(void)
{
if (m_nViewID)
return m_nViewID;
SetViewID(static_nViewID);
++static_nViewID;
return m_nViewID;
//UINT const id = m_nViewID ? m_nViewID : m_nViewID = static_nViewID++;
//return id;
}
/*+-------------------------------------------------------------------------*
* CAMCView::ScCompleteInitialization
*
* This function completes the initialization process for CAMCView. It
* is called from OnInitialUpdate.
*--------------------------------------------------------------------------*/
SC CAMCView::ScCompleteInitialization()
{
DECLARE_SC (sc, _T("CAMCView::ScCompleteInitialization"));
IScopeTree* const pScopeTree = GetScopeTree();
sc = ScCheckPointers (pScopeTree, E_UNEXPECTED);
if (sc)
return (sc);
pScopeTree->QueryIterator(&m_spScopeTreeIter);
pScopeTree->QueryNodeCallback(&m_spNodeCallback);
m_ViewData.m_spNodeCallback = GetNodeCallback();
sc = ScCheckPointers (m_ViewData.m_spNodeCallback, E_UNEXPECTED);
if (sc)
return (sc);
CAMCDoc* const pDoc = GetDocument();
sc = ScCheckPointers (pDoc, E_UNEXPECTED);
if (sc)
return (sc);
if (m_hMTNode == NULL)
{
MTNODEID const nodeID = pDoc->GetMTNodeIDForNewView();
HRESULT hr = pScopeTree->Find(nodeID, &m_hMTNode);
if (FAILED(hr) || m_hMTNode == 0)
{
sc.FromMMC (IDS_ExploredWindowFailed);
return (sc);
}
}
sc = m_spStandardToolbar->ScInitializeStdToolbar(this);
if (sc)
return (sc);
// Set the iterator to the correct node
m_spScopeTreeIter->SetCurrent(m_hMTNode);
bool fShowScopePane = IsScopePaneAllowed();
// Intialize the iterator and the callback interface
SetViewID(pDoc->GetViewIDForNewView());
GetViewID(); // initialized the view id if GetViewIDForNewView returned 0
// Insert the root node for this view
HNODE hNode = 0;
sc = pScopeTree->CreateNode (m_hMTNode, reinterpret_cast<LONG_PTR>(GetViewData()),
TRUE, &hNode);
if (sc)
return (sc);
sc = ScCheckPointers (hNode, E_UNEXPECTED);
if (sc)
return (sc);
HTREEITEM hti = m_pTreeCtrl->InsertNode(TVI_ROOT, hNode);
m_htiStartingSelectedNode = hti;
// If the persisted state is expanded, call INodeCallback::Expand
m_pTreeCtrl->Expand(hti, TVE_EXPAND);
/*
* If a scope pane is permitted in this window, set the scope
* pane visible, and modify the scope pane & favorites toolbar
* buttons to the proper checked state.
*/
sc = ScShowScopePane (fShowScopePane, true);
if (sc)
return (sc);
LPUNKNOWN pUnkResultsPane = NULL;
pUnkResultsPane = GetPaneUnknown(ePane_Results);
m_pTreeCtrl->m_spNodeManager->SetResultView(pUnkResultsPane);
DeferRecalcLayout();
m_pHistoryList->Clear();
IdentifyRootNode ();
// Select the root item
hti = m_pTreeCtrl->GetRootItem();
m_pTreeCtrl->SelectItem(hti);
/*
* if the document has a custom icon, use it on this window
*/
if (pDoc->HasCustomIcon())
{
GetParentFrame()->SetIcon (pDoc->GetCustomIcon(true), true);
GetParentFrame()->SetIcon (pDoc->GetCustomIcon(false), false);
}
/*
* we just initialized, so the view isn't dirty
*/
SetDirty (false);
return (sc);
}
void CAMCView::OnInitialUpdate()
{
DECLARE_SC (sc, _T("CAMCView::OnInitialUpdate"));
CView::OnInitialUpdate();
sc = ScCompleteInitialization ();
if (sc)
return;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScDocumentLoadCompleted
//
// Synopsis: The document is completely loaded so all the objects
// that initialize themself from document are in valid
// state. Any initialization performed earlier using invalid
// data can be now re-initialized with proper data.
//
// The above CAMCView::ScCompleteInitialization is called
// during the loading of views, thus the document is not
// completely loaded yet.
//
// Arguments: [pDoc] - [in] the CAMCDoc object
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScDocumentLoadCompleted (CAMCDoc *pDoc)
{
DECLARE_SC(sc, _T("CAMCView::ScDocumentLoadCompleted"));
sc = ScCheckPointers(pDoc);
if (sc)
return sc;
// 1. Need to hide toolbutton "Show/Hide scopetree".
// The FrameState is loaded after views when CAMCDoc loads document. And it contains
// whether the "View Customization" is enabled or not. If "View customization" is
// disabled then we need to disable "Show ScopeTree" button.
if (! pDoc->AllowViewCustomization())
{
CStandardToolbar* pStdToolbar = GetStdToolbar();
sc = ScCheckPointers(pStdToolbar, E_UNEXPECTED);
if (sc)
return (sc);
sc = pStdToolbar->ScEnableScopePaneBtn (false);
if (sc)
return (sc);
}
return (sc);
}
/*--------------------------------------------------------------------------*
* CAMCView::IdentifyRootNode
*
* This functions determines if this view is rooted at a non-persistent
* dynamic node. If so, we won't persist this view at save time.
*--------------------------------------------------------------------------*/
void CAMCView::IdentifyRootNode ()
{
// In order to get results from GetRootNodePath that are meaningful
// in this context, there needs to be a root item in the tree.
ASSERT (m_pTreeCtrl->GetRootItem() != NULL);
CBookmark bm;
HRESULT hr = GetRootNodePath (&bm);
ASSERT (SUCCEEDED (hr) == bm.IsValid());
m_fRootedAtNonPersistedDynamicNode = (hr != S_OK);
}
void GetFullPath(CAMCTreeView &ctc, HTREEITEM hti, CString &strPath)
{
TRACE_FUNCTION(GetFullPath);
if (hti == NULL)
{
strPath = _T("");
return;
}
GetFullPath(ctc, ctc.GetParentItem(hti), strPath);
if (strPath.GetLength() > 0)
strPath += _T('\\');
HNODE hNode = ctc.GetItemNode(hti);
INodeCallback* spCallback = ctc.GetNodeCallback();
ASSERT(spCallback != NULL);
tstring strName;
HRESULT const hr = spCallback->GetDisplayName(hNode, strName);
strPath += strName.data();
}
LPCTSTR CAMCView::GetWindowTitle(void)
{
TRACE_METHOD(CAMCView, GetWindowTitle);
if (HasCustomTitle() && (m_spNodeCallback != NULL))
{
HNODE hNode = GetSelectedNode();
if (hNode != NULL)
{
tstring strWindowTitle;
if (SUCCEEDED(m_spNodeCallback->GetWindowTitle(hNode, strWindowTitle)))
{
m_strWindowTitle = strWindowTitle.data();
return m_strWindowTitle;
}
}
}
if (m_pTreeCtrl == NULL)
{
m_strWindowTitle.Empty();
}
else
{
GetFullPath(*m_pTreeCtrl,
m_pTreeCtrl->GetSelectedItem(),
m_strWindowTitle);
}
return m_strWindowTitle;
}
void CAMCView::SelectNode(MTNODEID ID, GUID &guidTaskpad)
{
ScSelectNode(ID);
// After setting the taskpad enable/disable save list button
CStandardToolbar* pStdToolbar = GetStdToolbar();
ASSERT(NULL != pStdToolbar);
if (NULL != pStdToolbar)
{
pStdToolbar->ScEnableExportList(GetListSize() > 0 /*Enable only if LV has items*/);
}
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScSelectNode
//
// Synopsis: Select the given node. Normally if the node is not available
// then we select nearest parent or child. But if bSelectExactNode
// is true then have to select the exact node else do not select any node.
//
// Arguments: [ID] - [in] node that needs to be selected.
// [bSelectExactNode] - [in] select exact node or not?
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScSelectNode (MTNODEID ID, bool bSelectExactNode)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC (sc, _T("CAMCView::ScSelectNode"));
IScopeTree* pIST = GetScopeTreePtr();
sc = ScCheckPointers(pIST, m_pTreeCtrl, E_UNEXPECTED);
if (sc)
return sc;
long length = 0;
CCoTaskMemPtr<MTNODEID> spIDs;
sc = pIST->GetIDPath(ID, &spIDs, &length);
if (sc)
return (sc);
if ( (length < 1) || (spIDs == NULL) )
return (sc = E_FAIL);
sc = m_pTreeCtrl->ScSelectNode(spIDs, length, bSelectExactNode);
// If select exact node is specified and the node could not be
// selected then return error without tracing it.
if (bSelectExactNode && (sc == ScFromMMC(IDS_NODE_NOT_FOUND)) )
{
SC scNoTrace = sc;
sc.Clear();
return scNoTrace;
}
if (sc)
return sc;
SetDirty();
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScExpandNode
*
* PURPOSE: Expands the tree up to the specified node. The expansion can occur
* either visually, where the user sees the expansion, or nonvisually,
* where all the child items are added but there is no visual effect.
*
* PARAMETERS:
* MTNODEID id : id of node to expand
* bool bExpand : true to expand the node, false to collapse
* bool bExpandVisually : true to show the changes, else false.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScExpandNode (
MTNODEID id,
bool fExpand,
bool fExpandVisually)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC (sc, _T("CAMCView::ScExpandNode"));
IScopeTree* pIST = GetScopeTreePtr();
ASSERT(pIST != NULL);
if (!pIST)
return (sc = E_NOINTERFACE);
long length = 0;
CCoTaskMemPtr<MTNODEID> spIDs;
sc = pIST->GetIDPath(id, &spIDs, &length);
if (sc)
return (sc);
ASSERT(length);
ASSERT(spIDs);
ASSERT(m_pTreeCtrl != NULL);
if (m_pTreeCtrl)
m_pTreeCtrl->ExpandNode(spIDs, length, fExpand, fExpandVisually);
return (sc);
}
ViewSettings::ViewSettings(CAMCView* v)
: m_nViewID(v->m_nViewID), m_bDescriptionbarVisible(v->IsDescBarVisible()),
m_nViewMode(v->m_nViewMode), m_nListViewStyle(v->GetDefaultListViewStyle()),
m_DefaultLVStyle(v->m_DefaultLVStyle), m_bScopePaneVisible(v->IsScopePaneVisible())
{
ASSERT(v != NULL);
v->GetPaneInfo (CConsoleView::ePane_ScopeTree, &m_Scope.cxWidth, &m_Scope.cxMin);
v->GetDefaultColumnWidths(m_DefaultColumnWidths);
}
/*
* The location and hidden fields of the scope structure were redundant and are
* no longer used. Both fields were used to indicate when the scope pane was
* hidden, which is also determined by the FLAG1_SCOPE_VISIBLE flag. The space
* has been retained to avoid changing the persisted structure.
*/
struct PersistedViewData
{
WINDOWPLACEMENT windowPlacement;
struct
{
int location; // not used, but kept for compatibility
int min;
int ideal;
BOOL hidden; // not used, but kept for compatibility
} scope;
int viewMode;
long listViewStyle;
ULONG ulFlag1;
int viewID;
BOOL descriptionBarVisible;
int defaultColumnWidth[2];
};
/*
* The sense of the FLAG1_NO_xxx flags is negative. That is, when a
* FLAG1_NO_xxx flag is set, its corresponding UI element is *not*
* displayed. This is to maintain compatibility with console files
* created before the existence of the FLAG1_NO_xxx flags. These
* consoles always had all UI elements displayed, and the then-unused
* bits in their flags field were defaulted to 0. To maintain
* compatibility, we have to maintain that (0 == on).
*/
#define FLAG1_SCOPE_PANE_VISIBLE 0x00000001
#define FLAG1_NO_STD_MENUS 0x00000002
#define FLAG1_NO_STD_BUTTONS 0x00000004
#define FLAG1_NO_SNAPIN_MENUS 0x00000008
#define FLAG1_NO_SNAPIN_BUTTONS 0x00000010
#define FLAG1_DISABLE_SCOPEPANE 0x00000020
#define FLAG1_DISABLE_STD_TOOLBARS 0x00000040
#define FLAG1_CUSTOM_TITLE 0x00000080
#define FLAG1_NO_STATUS_BAR 0x00000100
#define FLAG1_CREATED_IN_USER_MODE 0x00000200 // used to be named FLAG1_NO_AUTHOR_MODE
//#define FLAG1_FAVORITES_SELECTED 0x00000400 // unused, but don't recycle (for compatibility)
#define FLAG1_NO_TREE_ALLOWED 0x00000800 // used for compatibility with MMC1.2 in CAMCView::Load.
// Do not use for any other purposes.
#define FLAG1_NO_TASKPAD_TABS 0x00001000
/***************************************************************************\
*
* ARRAY: mappedViewModes
*
* PURPOSE: provides map to be used when persisting ViewMode enumeration
*
\***************************************************************************/
static const EnumLiteral mappedViewModes[] =
{
{ MMCLV_VIEWSTYLE_ICON, XML_ENUM_LV_STYLE_ICON },
{ MMCLV_VIEWSTYLE_REPORT, XML_ENUM_LV_STYLE_REPORT },
{ MMCLV_VIEWSTYLE_SMALLICON, XML_ENUM_LV_STYLE_SMALLICON },
{ MMCLV_VIEWSTYLE_LIST, XML_ENUM_LV_STYLE_LIST },
{ MMCLV_VIEWSTYLE_FILTERED, XML_ENUM_LV_STYLE_FILTERED},
};
/***************************************************************************\
*
* ARRAY: mappedListStyles
*
* PURPOSE: provides map to be used when persisting ListView style flag
*
\***************************************************************************/
static const EnumLiteral mappedListStyles[] =
{
{ LVS_SINGLESEL, XML_BITFLAG_LV_STYLE_SINGLESEL },
{ LVS_SHOWSELALWAYS, XML_BITFLAG_LV_STYLE_SHOWSELALWAYS },
{ LVS_SORTASCENDING, XML_BITFLAG_LV_STYLE_SORTASCENDING },
{ LVS_SORTDESCENDING, XML_BITFLAG_LV_STYLE_SORTDESCENDING },
{ LVS_SHAREIMAGELISTS, XML_BITFLAG_LV_STYLE_SHAREIMAGELISTS },
{ LVS_NOLABELWRAP, XML_BITFLAG_LV_STYLE_NOLABELWRAP },
{ LVS_AUTOARRANGE, XML_BITFLAG_LV_STYLE_AUTOARRANGE },
{ LVS_EDITLABELS, XML_BITFLAG_LV_STYLE_EDITLABELS },
{ LVS_OWNERDATA, XML_BITFLAG_LV_STYLE_OWNERDATA },
{ LVS_NOSCROLL, XML_BITFLAG_LV_STYLE_NOSCROLL },
{ LVS_ALIGNLEFT, XML_BITFLAG_LV_STYLE_ALIGNLEFT },
{ LVS_OWNERDRAWFIXED, XML_BITFLAG_LV_STYLE_OWNERDRAWFIXED },
{ LVS_NOCOLUMNHEADER, XML_BITFLAG_LV_STYLE_NOCOLUMNHEADER },
{ LVS_NOSORTHEADER, XML_BITFLAG_LV_STYLE_NOSORTHEADER },
};
/***************************************************************************\
*
* ARRAY: mappedViewFlags
*
* PURPOSE: provides map to be used when persisting View flags
*
\***************************************************************************/
static const EnumLiteral mappedViewFlags[] =
{
{ FLAG1_SCOPE_PANE_VISIBLE, XML_BITFLAG_VIEW_SCOPE_PANE_VISIBLE },
{ FLAG1_NO_STD_MENUS, XML_BITFLAG_VIEW_NO_STD_MENUS },
{ FLAG1_NO_STD_BUTTONS, XML_BITFLAG_VIEW_NO_STD_BUTTONS },
{ FLAG1_NO_SNAPIN_MENUS, XML_BITFLAG_VIEW_NO_SNAPIN_MENUS },
{ FLAG1_NO_SNAPIN_BUTTONS, XML_BITFLAG_VIEW_NO_SNAPIN_BUTTONS },
{ FLAG1_DISABLE_SCOPEPANE, XML_BITFLAG_VIEW_DISABLE_SCOPEPANE },
{ FLAG1_DISABLE_STD_TOOLBARS, XML_BITFLAG_VIEW_DISABLE_STD_TOOLBARS },
{ FLAG1_CUSTOM_TITLE, XML_BITFLAG_VIEW_CUSTOM_TITLE },
{ FLAG1_NO_STATUS_BAR, XML_BITFLAG_VIEW_NO_STATUS_BAR },
{ FLAG1_CREATED_IN_USER_MODE, XML_BITFLAG_VIEW_CREATED_IN_USER_MODE },
{ FLAG1_NO_TASKPAD_TABS, XML_BITFLAG_VIEW_NO_TASKPAD_TABS },
};
/***************************************************************************\
*
* ARRAY: mappedSWCommands
*
* PURPOSE: provides mapping to persist show commands as literals
*
\***************************************************************************/
static const EnumLiteral mappedSWCommands[] =
{
{ SW_HIDE, XML_ENUM_SHOW_CMD_HIDE },
{ SW_SHOWNORMAL, XML_ENUM_SHOW_CMD_SHOWNORMAL },
{ SW_SHOWMINIMIZED, XML_ENUM_SHOW_CMD_SHOWMINIMIZED },
{ SW_SHOWMAXIMIZED, XML_ENUM_SHOW_CMD_SHOWMAXIMIZED },
{ SW_SHOWNOACTIVATE, XML_ENUM_SHOW_CMD_SHOWNOACTIVATE },
{ SW_SHOW, XML_ENUM_SHOW_CMD_SHOW },
{ SW_MINIMIZE, XML_ENUM_SHOW_CMD_MINIMIZE },
{ SW_SHOWMINNOACTIVE, XML_ENUM_SHOW_CMD_SHOWMINNOACTIVE },
{ SW_SHOWNA, XML_ENUM_SHOW_CMD_SHOWNA },
{ SW_RESTORE, XML_ENUM_SHOW_CMD_RESTORE },
{ SW_SHOWDEFAULT, XML_ENUM_SHOW_CMD_SHOWDEFAULT },
{ SW_FORCEMINIMIZE, XML_ENUM_SHOW_CMD_FORCEMINIMIZE },
};
/***************************************************************************\
*
* ARRAY: mappedWPFlags
*
* PURPOSE: provides mapping to persist WP flags
*
\***************************************************************************/
static const EnumLiteral mappedWPFlags[] =
{
{ WPF_SETMINPOSITION, XML_ENUM_WIN_PLACE_SETMINPOSITION },
{ WPF_RESTORETOMAXIMIZED, XML_ENUM_WIN_PLACE_RESTORETOMAXIMIZED },
#ifdef WPF_ASYNCWINDOWPLACEMENT
{ WPF_ASYNCWINDOWPLACEMENT, XML_ENUM_WIN_PLACE_ASYNCWINDOWPLACEMENT },
#else
{ 4, XML_ENUM_WIN_PLACE_ASYNCWINDOWPLACEMENT },
#endif
};
/*+-------------------------------------------------------------------------*
* PersistViewData(CPersistor &persistor, PersistedViewData viewData)
*
*
* PURPOSE: Persists a PersistedViewData object to the specified persistor.
*
*+-------------------------------------------------------------------------*/
void PersistViewData(CPersistor &persistor, PersistedViewData& viewData)
{
persistor.PersistAttribute(XML_ATTR_VIEW_ID, viewData.viewID);
// write out the windowPlacement structure.
persistor.Persist(CXMLWindowPlacement(viewData.windowPlacement));
// write out the scope structure
persistor.PersistAttribute(XML_ATTR_VIEW_SCOPE_WIDTH, viewData.scope.ideal);
if (persistor.IsLoading())
{
// initialize for compatibility;
viewData.scope.hidden = true;
viewData.scope.location = 0;
viewData.scope.min = 50;
}
// write out the remaining fields
CPersistor persistorSettings(persistor, XML_TAG_VIEW_SETTINGS_2);
// create wrapper to persist enumeration values as strings
CXMLEnumeration viewModePersistor(viewData.viewMode, mappedViewModes, countof(mappedViewModes));
// persist the wrapper
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_VIEW_MODE, viewModePersistor);
// create wrapper to persist flag values as strings
CXMLBitFlags viewStylePersistor(viewData.listViewStyle, mappedListStyles, countof(mappedListStyles));
// persist the wrapper
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_LIST_STYLE, viewStylePersistor);
// create wrapper to persist flag values as strings
CXMLBitFlags flagPersistor(viewData.ulFlag1, mappedViewFlags, countof(mappedViewFlags));
// persist the wrapper
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_FLAG, flagPersistor);
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_DB_VISIBLE, CXMLBoolean(viewData.descriptionBarVisible));
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_DEF_COL_W0, viewData.defaultColumnWidth[0]);
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_DEF_COL_W1, viewData.defaultColumnWidth[1]);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Persist
*
* PURPOSE: Persists the CAMCView object to the specified persistor. Based
* on CAMCView::Save.
*
* PARAMETERS:
* CPersistor& persistor :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CAMCView::Persist(CPersistor& persistor)
{
DECLARE_SC(sc, TEXT("CAMCView::Persist"));
HRESULT hr;
CBookmark bmr;
CBookmark bms;
if (persistor.IsStoring())
{
sc = GetRootNodePath(&bmr);
if (sc)
sc.Throw();
persistor.Persist(bmr, XML_NAME_ROOT_NODE); // ... its too late for root node when loading
sc = GetSelectedNodePath(&bms);
if (sc)
sc.Throw();
}
persistor.Persist(bms, XML_NAME_SELECTED_NODE);
// mostly copied from CAMCView::Save
// Get the parent frame
CWnd* const pParent = GetParent();
sc = ScCheckPointers(pParent,E_POINTER);
if (sc)
sc.Throw();
// Get the frames state data
PersistedViewData vd;
vd.windowPlacement.length = sizeof(vd.windowPlacement);
const BOOL bGotPlacement = pParent->GetWindowPlacement(&vd.windowPlacement);
if (!bGotPlacement)
sc.Throw(E_FAIL);
if (persistor.IsStoring())
{
/*
* If this window is minimized, make sure we set things up so the
* WINDOWPLACEMENT.ptMinPosition will be restored by SetWindowPlacement
* when we load. If we don't do this, it'll get some random min
* position, likely not what we want.
*/
if (vd.windowPlacement.showCmd == SW_SHOWMINIMIZED)
vd.windowPlacement.flags |= WPF_SETMINPOSITION;
GetPaneInfo(ePane_ScopeTree, &vd.scope.ideal, &vd.scope.min);
vd.viewMode = m_nViewMode;
vd.listViewStyle = GetDefaultListViewStyle();
vd.ulFlag1 = 0;
if (IsScopePaneVisible())
vd.ulFlag1 |= FLAG1_SCOPE_PANE_VISIBLE;
if (!IsAuthorModeView())
vd.ulFlag1 |= FLAG1_CREATED_IN_USER_MODE;
if (!(m_ViewData.m_dwToolbarsDisplayed & STD_MENUS))
vd.ulFlag1 |= FLAG1_NO_STD_MENUS;
if (!(m_ViewData.m_dwToolbarsDisplayed & STD_BUTTONS))
vd.ulFlag1 |= FLAG1_NO_STD_BUTTONS;
if (!(m_ViewData.m_dwToolbarsDisplayed & SNAPIN_MENUS))
vd.ulFlag1 |= FLAG1_NO_SNAPIN_MENUS;
if (!(m_ViewData.m_dwToolbarsDisplayed & SNAPIN_BUTTONS))
vd.ulFlag1 |= FLAG1_NO_SNAPIN_BUTTONS;
if (!(m_ViewData.m_dwToolbarsDisplayed & STATUS_BAR))
vd.ulFlag1 |= FLAG1_NO_STATUS_BAR;
if (!AreStdToolbarsAllowed ())
vd.ulFlag1 |= FLAG1_DISABLE_STD_TOOLBARS;
if (!IsScopePaneAllowed ())
vd.ulFlag1 |= FLAG1_DISABLE_SCOPEPANE;
if (HasCustomTitle ())
vd.ulFlag1 |= FLAG1_CUSTOM_TITLE;
if (!AreTaskpadTabsAllowed())
(vd.ulFlag1 |= FLAG1_NO_TASKPAD_TABS);
vd.viewID = GetViewID();
vd.descriptionBarVisible = IsDescBarVisible();
GetDefaultColumnWidths(vd.defaultColumnWidth);
}
PersistViewData(persistor,vd);
if (persistor.IsLoading())
{
ASSERT(int(m_nViewID) == vd.viewID);
m_ViewData.m_nViewID = m_nViewID = vd.viewID;
if (int(m_nViewID) >= static_nViewID)
static_nViewID = m_nViewID + 1;
//SetDefaultColumnWidths(vd.defaultColumnWidth);
SetDescBarVisible(vd.descriptionBarVisible);
// we shouldn't restore maximized window position
// since it may not be proper one for the current resolution
// related to bug #404118
WINDOWPLACEMENT orgPlacement;
ZeroMemory(&orgPlacement,sizeof(orgPlacement));
orgPlacement.length = sizeof(orgPlacement);
if (pParent->GetWindowPlacement(&orgPlacement))
{
vd.windowPlacement.ptMaxPosition = orgPlacement.ptMaxPosition;
}
m_ViewData.SetScopePaneVisible( 0 != (vd.ulFlag1 & FLAG1_SCOPE_PANE_VISIBLE) );
// Set the location and size of the frame
const BOOL bPlaced = pParent->SetWindowPlacement(&vd.windowPlacement);
if (!bPlaced)
sc.Throw(E_FAIL);
// Restore window settings
if (vd.ulFlag1 & FLAG1_DISABLE_SCOPEPANE)
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOSCOPEPANE;
if (vd.ulFlag1 & FLAG1_DISABLE_STD_TOOLBARS)
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOTOOLBARS;
if (vd.ulFlag1 & FLAG1_CUSTOM_TITLE)
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_CUSTOMTITLE;
SetAuthorModeView (!(vd.ulFlag1 & FLAG1_CREATED_IN_USER_MODE));
if ((vd.ulFlag1 & FLAG1_NO_TASKPAD_TABS))
SetTaskpadTabsAllowed(FALSE);
// Apply run time restrictions
// if at least one type of scope pane allowed then if the selected
// one is not allowed, switch to the other. If neither is allowed
// then keep the selection and hide the scope pane.
if (IsScopePaneAllowed())
{
// Restore scope pane settings
SetPaneInfo(ePane_ScopeTree, vd.scope.ideal, vd.scope.min);
sc = ScShowScopePane ( m_ViewData.IsScopePaneVisible() );
}
else
sc = ScShowScopePane (false);
if (sc)
sc.Throw();
// Force layout re-calculation
DeferRecalcLayout();
// Restore view style & view mode if persisted will be set by nodemgr.
SetDefaultListViewStyle(vd.listViewStyle);
DWORD dwToolbars = 0;
if (!(vd.ulFlag1 & FLAG1_NO_STD_MENUS))
dwToolbars |= STD_MENUS;
if (!(vd.ulFlag1 & FLAG1_NO_STD_BUTTONS))
dwToolbars |= STD_BUTTONS;
if (!(vd.ulFlag1 & FLAG1_NO_SNAPIN_MENUS))
dwToolbars |= SNAPIN_MENUS;
if (!(vd.ulFlag1 & FLAG1_NO_SNAPIN_BUTTONS))
dwToolbars |= SNAPIN_BUTTONS;
if (!(vd.ulFlag1 & FLAG1_NO_STATUS_BAR))
dwToolbars |= STATUS_BAR;
// display the status bar appropriately
if (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) != StatusBarOf (dwToolbars))
{
CChildFrame* pFrame = GetParentFrame ();
if (pFrame != NULL)
{
pFrame->ToggleStatusBar();
SetStatusBarVisible(!IsStatusBarVisible());
ASSERT (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) ==
StatusBarOf (dwToolbars));
}
}
// display the appropriate toolbars
if (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) != ToolbarsOf (dwToolbars))
{
m_spNodeCallback->UpdateWindowLayout(
reinterpret_cast<LONG_PTR>(&m_ViewData), dwToolbars);
ASSERT (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) ==
ToolbarsOf (dwToolbars));
}
// Update the status of MMC menus.
sc = ScUpdateMMCMenus();
if (sc)
sc.Throw();
SetDirty (false);
m_pHistoryList->Clear();
}
SaveStartingSelectedNode();
if (persistor.IsLoading())
{
SC sc;
IScopeTree* const pScopeTree = GetScopeTreePtr();
if(!pScopeTree)
{
sc = E_UNEXPECTED;
return;
}
MTNODEID idTemp = 0;
bool bExactMatchFound = false; // out value from GetNodeIDFromBookmark, unused
sc = pScopeTree->GetNodeIDFromBookmark(bms, &idTemp, bExactMatchFound);
if(sc)
return;
sc = ScSelectNode(idTemp);
if(sc)
return;
}
// if we've stored everything -we're clean
if (persistor.IsStoring())
SetDirty (false);
}
bool CAMCView::Load(IStream& stream)
// Caller is responsible for notifying user if false is returned
{
TRACE_METHOD(CAMCView, Load);
SetDirty (false);
// Read the view data from the stream.
ASSERT(&stream);
if (!&stream)
return false;
PersistedViewData pvd;
unsigned long bytesRead;
HRESULT hr = stream.Read(&pvd, sizeof(pvd), &bytesRead);
ASSERT(SUCCEEDED(hr) && bytesRead == sizeof(pvd));
if (FAILED(hr))
return false;
ASSERT(int(m_nViewID) == pvd.viewID);
m_ViewData.m_nViewID = m_nViewID = pvd.viewID;
if (int(m_nViewID) >= static_nViewID)
static_nViewID = m_nViewID + 1;
//SetDefaultColumnWidths(pvd.defaultColumnWidth);
SetDescBarVisible(pvd.descriptionBarVisible);
// Get the parent frame
CWnd* const pParent = GetParent();
ASSERT(pParent != NULL);
if (pParent == NULL)
return false;
// we shouldn't restore maximized window position
// since it may not be proper one for the current resolution
// related to bug #404118
WINDOWPLACEMENT orgPlacement;
ZeroMemory(&orgPlacement,sizeof(orgPlacement));
orgPlacement.length = sizeof(orgPlacement);
if (pParent->GetWindowPlacement(&orgPlacement))
{
pvd.windowPlacement.ptMaxPosition = orgPlacement.ptMaxPosition;
}
// Set the location and size of the frame
const BOOL bPlaced = pParent->SetWindowPlacement(&pvd.windowPlacement);
ASSERT(bPlaced != FALSE);
if (bPlaced == FALSE)
return false;
// Restore window settings
if (pvd.ulFlag1 & FLAG1_DISABLE_SCOPEPANE)
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOSCOPEPANE;
if (pvd.ulFlag1 & FLAG1_DISABLE_STD_TOOLBARS)
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOTOOLBARS;
if (pvd.ulFlag1 & FLAG1_CUSTOM_TITLE)
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_CUSTOMTITLE;
SetAuthorModeView (!(pvd.ulFlag1 & FLAG1_CREATED_IN_USER_MODE));
if ((pvd.ulFlag1 & FLAG1_NO_TASKPAD_TABS))
SetTaskpadTabsAllowed(FALSE);
// Restore scope pane settings
SetPaneInfo(ePane_ScopeTree, pvd.scope.ideal, pvd.scope.min);
// The FLAG1_NO_TREE_ALLOWED is used only for compatibility with MMC1.2 console files
// It is a relic from old console files that does not exist in MMC2.0 console files.
bool bScopeTreeNotAllowed = (pvd.ulFlag1 & FLAG1_NO_TREE_ALLOWED);
SC sc;
if ( (IsScopePaneAllowed()) && (! bScopeTreeNotAllowed) )
sc = ScShowScopePane ((pvd.ulFlag1 & FLAG1_SCOPE_PANE_VISIBLE) != 0);
else
sc = ScShowScopePane (false);
if (sc)
return (false);
// Force layout re-calculation
DeferRecalcLayout();
// Restore view style & view mode if persisted will be set by nodemgr.
SetDefaultListViewStyle(pvd.listViewStyle);
DWORD dwToolbars = 0;
if (!(pvd.ulFlag1 & FLAG1_NO_STD_MENUS))
dwToolbars |= STD_MENUS;
if (!(pvd.ulFlag1 & FLAG1_NO_STD_BUTTONS))
dwToolbars |= STD_BUTTONS;
if (!(pvd.ulFlag1 & FLAG1_NO_SNAPIN_MENUS))
dwToolbars |= SNAPIN_MENUS;
if (!(pvd.ulFlag1 & FLAG1_NO_SNAPIN_BUTTONS))
dwToolbars |= SNAPIN_BUTTONS;
if (!(pvd.ulFlag1 & FLAG1_NO_STATUS_BAR))
dwToolbars |= STATUS_BAR;
// display the status bar appropriately
if (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) != StatusBarOf (dwToolbars))
{
CChildFrame* pFrame = GetParentFrame ();
if (pFrame != NULL)
{
pFrame->ToggleStatusBar();
SetStatusBarVisible(!IsStatusBarVisible());
ASSERT (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) ==
StatusBarOf (dwToolbars));
}
}
// display the appropriate toolbars
if (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) != ToolbarsOf (dwToolbars))
{
m_spNodeCallback->UpdateWindowLayout(
reinterpret_cast<LONG_PTR>(&m_ViewData), dwToolbars);
ASSERT (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) ==
ToolbarsOf (dwToolbars));
}
// Update the status of MMC menus.
sc = ScUpdateMMCMenus();
if (sc)
return false;
SetDirty (false);
m_pHistoryList->Clear();
return true;
}
//+-------------------------------------------------------------------
//
// Member: ScSpecialResultpaneSelectionActivate
//
// Synopsis: Only the list(/Web/OCX) or the tree can be "active" from the point
// of view of selected items and MMCN_SELECT. This is not
// the same as the MFC concept of "active view". There are a couple
// of views that cannot be active in this sense, such as the taskpad
// and tab views.
// When the active view (according to this definition) changes, this
// function is called. Thus, ScTreeViewSelectionActivate and
// ScListViewSelectionActivate/ScSpecialResultpaneSelectionActivate
// are always called in pairs when the activation changes, one to handle
// deactivation, and one to handle activation.
//
// Consider the following scenario
// 1) The tree view has (MFC/windows style) focus.
// 2) The user clicks on the taskpad view
// Result - selection activation does not change from the tree. All verbs
// still correspond to the selected tree item.
// 3) The user clicks on the folder view
// Result - once again, selection activation does not chang
// 4) The user clicks on one of the result views eg the list
// Result - ScTreeViewSelectionActivate(false) and ScListViewSelectionActivate(true)
// Thus verbs and the toolbar now correspond to the selected list item(s).
// 5) The user clicks on the taskpad view.
// Result - as in step 2, nothing happens
// 6) The user clicks on the result view
// Result - because the active view has not changed, nothing happens.
//
// Arguments: [bActivate] - special result pane is selected/de-selected.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScSpecialResultpaneSelectionActivate(bool bActivate)
{
DECLARE_SC(sc, TEXT("CAMCView::ScSpecialResultpaneSelectionActivate"));
/*
* Bug 331904: prevent recursion
*/
if (m_fActivatingSpecialResultPane)
{
TRACE (_T("CAMCView:ScSpecialResultpaneSelectionActivate: shorting out of recursion\n"));
return sc;
}
do
{
m_fActivatingSpecialResultPane = true;
HNODE hNode = GetSelectedNode();
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = FALSE;
selInfo.m_bDueToFocusChange = TRUE;
selInfo.m_bBackground = FALSE;
INodeCallback* pNodeCallBack = GetNodeCallback();
if (HasOCX())
{
selInfo.m_bResultPaneIsOCX = TRUE;
selInfo.m_lCookie = LVDATA_CUSTOMOCX;
}
else if (HasWebBrowser())
{
selInfo.m_bResultPaneIsWeb = TRUE;
selInfo.m_lCookie = LVDATA_CUSTOMWEB;
}
else
{
// Dont do anything. Just return.
m_fActivatingSpecialResultPane = false;
return sc;
}
sc = ScNotifySelect (pNodeCallBack, hNode, false /*fMultiSelect*/, bActivate, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
} while ( FALSE );
m_fActivatingSpecialResultPane = false;
return sc;
}
void CAMCView::CloseView()
{
DECLARE_SC(sc, TEXT("CAMCView::CloseView"));
TRACE_METHOD(CAMCView, CloseView);
// fire event to script
// this needs to be done while view is still 'alive'
sc = ScFireEvent(CAMCViewObserver::ScOnCloseView, this);
if (sc)
sc.TraceAndClear();
IScopeTree* const pScopeTree = GetScopeTreePtr();
ASSERT(pScopeTree != NULL);
if (pScopeTree != NULL)
{
HRESULT hr = pScopeTree->CloseView(m_nViewID);
ASSERT(hr == S_OK);
}
}
void CAMCView::OnDestroy()
{
TRACE_METHOD(CAMCView, OnDestroy);
// send the view destroy notification to all observers.
SC sc;
sc = ScFireEvent(CAMCViewObserver::ScOnViewDestroyed, this);
if(sc)
sc.TraceAndClear();
if (IsPersisted())
{
if(m_pDocument != NULL)
m_pDocument->SetModifiedFlag(TRUE);
SetDirty();
}
CDocument* pDoc = GetDocument();
ASSERT(pDoc != NULL);
// if we were in ListPad-mode....
// this must be detached before destroying the Scopetree,
// because we need to send a notify to the snapin,
// which we get from the hnode.
if (m_pListCtrl->IsListPad())
{
sc = m_pListCtrl->ScAttachToListPad (NULL, NULL);
if(sc)
sc.TraceAndClear();
}
// make sure to stop running scripts if we have a web browser
if( HasWebBrowser() )
{
ASSERT( m_pWebViewCtrl != NULL );
if ( m_pWebViewCtrl != NULL )
{
m_pWebViewCtrl->DestroyWindow();
m_pWebViewCtrl = NULL;
}
}
// make sure to stop running scripts if we have a view extension
if ( m_fViewExtended )
{
ASSERT( m_pViewExtensionCtrl != NULL );
if ( m_pViewExtensionCtrl != NULL )
{
m_pViewExtensionCtrl->DestroyWindow();
m_pViewExtensionCtrl = NULL;
}
}
if (m_pTreeCtrl != NULL)
{
HNODE hNode = GetSelectedNode();
if (hNode)
m_pTreeCtrl->OnDeSelectNode(hNode);
m_pTreeCtrl->DeleteScopeTree();
}
IScopeTree* const pScopeTree = GetScopeTreePtr();
ASSERT(pScopeTree != NULL);
if (pScopeTree != NULL)
{
HRESULT hr = pScopeTree->DeleteView(m_nViewID);
ASSERT(hr == S_OK);
}
CView::OnDestroy();
}
void CAMCView::OnUpdateFileSnapinmanager(CCmdUI* pCmdUI)
{
pCmdUI->Enable ();
}
void CAMCView::OnSize(UINT nType, int cx, int cy)
{
TRACE_METHOD(CAMCView, OnSize);
CView::OnSize(nType, cx, cy);
if (nType != SIZE_MINIMIZED)
RecalcLayout();
}
SC CAMCView::ScToggleDescriptionBar()
{
TRACE_METHOD(CAMCView, ScToggleDescriptionBar);
AFX_MANAGE_STATE (AfxGetAppModuleState());
SetDescBarVisible (!IsDescBarVisible());
SetDirty();
/*
* Don't defer this layout. This may be called by the Customize View
* dialog which wants to see its updates in real time. It will be
* sitting in a modal message loop so we won't get a chance to precess
* our idle task.
*/
RecalcLayout();
return (S_OK);
}
SC CAMCView::ScToggleStatusBar()
{
TRACE_METHOD(CAMCView, ScToggleStatusBar);
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC (sc, _T("CAMCView::ScToggleStatusBar"));
CChildFrame* pFrame = GetParentFrame();
sc = ScCheckPointers (pFrame, E_UNEXPECTED);
if (sc)
return (sc);
pFrame->ToggleStatusBar();
SetStatusBarVisible (!IsStatusBarVisible());
SetDirty();
return (sc);
}
SC CAMCView::ScToggleTaskpadTabs()
{
TRACE_METHOD(CAMCView, ScToggleTaskpadTabs);
AFX_MANAGE_STATE (AfxGetAppModuleState());
SetTaskpadTabsAllowed (!AreTaskpadTabsAllowed());
SetDirty();
/*
* Don't defer this layout. This message will be sent by the
* Customize View dialog which wants to see its updates in
* real time. It will be sitting in a modal message loop so
* we won't get a chance to precess our idle task.
*/
RecalcLayout();
return (S_OK);
}
SC CAMCView::ScToggleScopePane()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC (sc, _T("CAMCView::ScToggleScopePane"));
sc = ScShowScopePane (!IsScopePaneVisible());
if (sc)
return (sc);
return (sc);
}
void CAMCView::OnActionMenu(CPoint point, LPCRECT prcExclude)
{
TRACE_METHOD(CAMCView, OnActionMenu);
UINT fHitTestFlags = 0;
HTREEITEM hTreeItem = m_pTreeCtrl->GetSelectedItem( );
ASSERT_VALID (this);
/*
* BUG: 99643
* Right now there is inconsistency between what you get by action menu & right click
* on a location in taskpad. The action menu always assumes it is tree or if result
* pane it is list or ocx or web or background. So if a taskpad is selected it assumes
* the corresponding list item is selected or tree item is selected or background.
* But right click on taskpad calls CAMCView::OnContextMenu which determines nothing
* is selected and does nothing. This needs to be addressed.
*/
ASSERT(eActivePaneNone != m_eCurrentActivePane);
if (eActivePaneScope == m_eCurrentActivePane)
{
if (hTreeItem != NULL)
{
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hTreeItem);
OnContextMenuForTreeItem(INDEX_INVALID, hNode, point, CCT_SCOPE, hTreeItem, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
}
else
{
OnContextMenuForTreeBackground(point, prcExclude, false/*bAllowDefaultItem*/);
}
}
else
{
if (HasListOrListPad())
{
int cSel = m_pListCtrl->GetSelectedCount();
int nIndex = -1;
LPARAM lvData = LVDATA_ERROR;
if (cSel == 0)
lvData = LVDATA_BACKGROUND;
else if (cSel == 1)
nIndex = _GetLVSelectedItemData(&lvData);
else if (cSel > 1)
lvData = LVDATA_MULTISELECT;
ASSERT(lvData != LVDATA_ERROR);
if (lvData == LVDATA_ERROR)
return;
if (lvData == LVDATA_BACKGROUND)
{
// Find out which pane has focus to set the CMINFO_DO_SCOPEPANE_MENU flag.
HNODE hNode = GetSelectedNode();
DATA_OBJECT_TYPES ePaneType = (GetParentFrame()->GetActiveView() == m_pTreeCtrl) ? CCT_SCOPE : CCT_RESULT;
OnContextMenuForTreeItem(INDEX_BACKGROUND, hNode, point, ePaneType, hTreeItem, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
return;
}
else if (lvData == LVDATA_MULTISELECT)
{
OnContextMenuForListItem(INDEX_MULTISELECTION, NULL, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
}
else
{
if (IsVirtualList())
{
OnContextMenuForListItem(nIndex, (HRESULTITEM)NULL, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
}
else
{
CResultItem* pri = CResultItem::FromHandle (lvData);
if (pri != NULL)
{
if (pri->IsScopeItem())
OnContextMenuForTreeItem(nIndex, pri->GetScopeNode(), point, CCT_RESULT, NULL, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
else
OnContextMenuForListItem(nIndex, lvData, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
}
}
}
}
else
{
// The active window may be a web page or task pad or ocx.
LPARAM lvData = LVDATA_ERROR;
if (HasOCX())
{
lvData = LVDATA_CUSTOMOCX;
OnContextMenuForListItem(INDEX_OCXPANE, (HRESULTITEM)lvData, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
}
else if (HasWebBrowser())
{
lvData = LVDATA_CUSTOMWEB;
OnContextMenuForListItem(INDEX_WEBPANE, (HRESULTITEM)lvData, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
}
else
{
// Some unknown window has the focus.
ASSERT(FALSE && "Unknown window has the focus");
}
}
}
}
SC CAMCView::ScUpOneLevel()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
TRACE_METHOD(CAMCView, ScUpOneLevel);
DECLARE_SC (sc, _T("CAMCView::ScUpOneLevel"));
sc = E_FAIL;
if (m_pTreeCtrl)
{
HTREEITEM htiParent = m_pTreeCtrl->GetParentItem (m_pTreeCtrl->GetSelectedItem());
if (htiParent)
{
m_pTreeCtrl->SelectItem(htiParent);
m_pTreeCtrl->EnsureVisible(htiParent);
sc = S_OK;
}
}
return (sc);
}
void CAMCView::OnViewMenu(CPoint point, LPCRECT prcExclude)
{
TRACE_METHOD(CAMCView, OnViewMenu);
OnContextMenuForListItem (INDEX_BACKGROUND, NULL, point,
MMC_CONTEXT_MENU_VIEW, prcExclude,
false /*bAllowDefaultItem*/);
}
void CAMCView::OnDrawClipboard()
{
if (m_htiCut)
{
m_pTreeCtrl->SetItemState(m_htiCut, 0, TVIS_CUT);
}
else
{
m_pListCtrl->CutSelectedItems(FALSE);
}
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::OnSettingChange
*
* PURPOSE: Handles WM_SETTINGCHANGE. Recalculates the layout. The
* result folder tab control needs this, for instance.
*
* PARAMETERS:
* UINT uFlags :
* LPCTSTR lpszSection :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CAMCView::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
DeferRecalcLayout();
}
void CAMCView::OnUpdatePasteBtn()
{
DECLARE_SC(sc, TEXT("CAMCView::OnUpdatePasteBtn"));
HNODE hNode = NULL;
LPARAM lvData = NULL;
bool bScope = FALSE;
sc = ScGetFocusedItem(hNode, lvData, bScope);
if (sc)
return;
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(hNode, pNC, E_UNEXPECTED);
if (sc)
return;
sc = pNC->UpdatePasteButton(hNode, bScope, lvData);
if (sc)
return;
return;
}
void CAMCView::OnContextHelp()
{
ScContextHelp();
}
SC CAMCView::ScContextHelp ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
m_fSnapinDisplayedHelp = false;
SC sc = SendGenericNotify(NCLBK_CONTEXTHELP);
// if snap-in hasn't called us to display a topic
// and it has not handled the notification then
// display MMC topic by default
if (!m_fSnapinDisplayedHelp && (sc.ToHr() != S_OK))
sc = ScHelpTopics ();
if (sc)
TraceError (_T("CAMCView::ScContextHelp"), sc);
return (sc);
}
void CAMCView::OnSnapInHelp()
{
SendGenericNotify(NCLBK_SNAPINHELP);
}
void CAMCView::OnSnapinAbout()
{
DECLARE_SC(sc, TEXT("CAMCView::OnSnapinAbout"));
HNODE hNode = GetSelectedNode();
sc = ScCheckPointers((void*) hNode, E_UNEXPECTED);
if (sc)
return;
INodeCallback *pNC = GetNodeCallback();
sc = ScCheckPointers(pNC, E_UNEXPECTED);
if (sc)
return;
sc = pNC->ShowAboutInformation(hNode);
if (sc)
return;
return;
}
void CAMCView::OnHelpTopics()
{
ScHelpTopics();
}
SC CAMCView::ScHelpWorker (LPCTSTR pszHelpTopic)
{
DECLARE_SC (sc, _T("CAMCView::ScShowSnapinHelpTopic"));
USES_CONVERSION;
/*
* generation of the help collection might take a while, so display
* a wait cursor
*/
CWaitCursor wait;
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
CAMCDoc* pdoc = GetDocument();
// Point helpdoc info to current console file path
if (pdoc->GetPathName().IsEmpty())
pdoc->GetHelpDocInfo()->m_pszFileName = NULL;
else
pdoc->GetHelpDocInfo()->m_pszFileName = T2COLE(pdoc->GetPathName());
/*
* smart pointer for automatic deletion of the help file name
*/
CCoTaskMemPtr<WCHAR> spszHelpFile;
sc = pNC->Notify (0, NCLBK_GETHELPDOC,
reinterpret_cast<LPARAM>(pdoc->GetHelpDocInfo()),
reinterpret_cast<LPARAM>(&spszHelpFile));
if (sc)
return (sc);
CAMCApp* pAMCApp = AMCGetApp();
if (NULL == pAMCApp)
return (sc = E_UNEXPECTED);
sc = pAMCApp->ScShowHtmlHelp(W2T(spszHelpFile), (DWORD_PTR) pszHelpTopic);
return (sc);
}
SC CAMCView::ScHelpTopics ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
return (ScHelpWorker (NULL));
}
SC CAMCView::ScShowSnapinHelpTopic (LPCTSTR pszHelpTopic)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
CString strTopicPath;
// Add protocol prefix to topic string
if (pszHelpTopic != NULL)
{
strTopicPath = _T("ms-its:");
strTopicPath += pszHelpTopic;
}
SC sc = ScHelpWorker (strTopicPath);
if (!sc)
m_fSnapinDisplayedHelp = true;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::UpdateSnapInHelpMenus
//
// Synopsis: Update the following Help menu items
// a) Help on <Snapin> (if snapin does not support HTML help)
// b) About <Snapin> (if snapin supports about object)
//
// Arguments: [pMenu] - The help popup menu.
//
//--------------------------------------------------------------------
void CAMCView::UpdateSnapInHelpMenus(CMenu* pMenu)
{
DECLARE_SC(sc, TEXT("CAMCView::UpdateSnapInHelpMenus"));
sc = ScCheckPointers(pMenu);
if (sc)
return;
ASSERT_VALID (this);
HNODE hNode = GetSelectedNode();
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(hNode, pNC, E_UNEXPECTED);
if (sc)
goto Error;
// Empty block for goto's
{
// First Make sure this is not a dummy substitute snapin.
bool bDummySnapin = false;
sc = pNC->IsDummySnapin (hNode, bDummySnapin);
if (sc)
goto Error;
if (bDummySnapin)
goto Error;
// Get the snapin name for "Help on <SnapinName>" or "About <SnapinName>" menus
CCoTaskMemPtr<WCHAR> spszName;
CString strMenu;
// Try to get name of snap-in for custom menu item
bool bSnapinNameValid = false;
sc = pNC->GetSnapinName(hNode, &spszName, bSnapinNameValid);
if (sc)
goto Error;
ASSERT( spszName != NULL || bSnapinNameValid );
USES_CONVERSION;
// if snapin supports html help, don't give it it's own help command
bool bStandardHelpExists = false;
sc = pNC->DoesStandardSnapinHelpExist(hNode, bStandardHelpExists);
if (sc)
goto Error;
if (bStandardHelpExists)
{
pMenu->DeleteMenu(ID_HELP_SNAPINHELP, MF_BYCOMMAND);
}
else
{
if (bSnapinNameValid)
{
// "Help on <SnapinName>"
LoadString(strMenu, IDS_HELP_ON);
AfxFormatString1(strMenu, IDS_HELP_ON, OLE2T(spszName));
}
else
{
// ""Help on Snap-in"
LoadString(strMenu, IDS_HELP_ON_SNAPIN);
}
// Either add or modify the custom help menu item
if (pMenu->GetMenuState(ID_HELP_SNAPINHELP, MF_BYCOMMAND) == (UINT)-1)
{
pMenu->InsertMenu(ID_HELP_HELPTOPICS, MF_BYCOMMAND|MF_ENABLED, ID_HELP_SNAPINHELP, strMenu);
}
else
{
pMenu->ModifyMenu(ID_HELP_SNAPINHELP, MF_BYCOMMAND|MF_ENABLED, ID_HELP_SNAPINHELP, strMenu);
}
}
/* Now add the About <Snapin> menu*/
bool bAboutExists = false;
SC scNoTrace = pNC->DoesAboutExist(hNode, &bAboutExists);
if ( (scNoTrace.IsError()) || (!bAboutExists) )
{
pMenu->DeleteMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND);
return;
}
if (bSnapinNameValid)
{
// "About on <SnapinName>"
AfxFormatString1(strMenu, IDS_ABOUT_ON, OLE2T(spszName));
}
else
{
// Cant get name just delete & return
pMenu->DeleteMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND);
return;
}
if (pMenu->GetMenuState(ID_SNAPIN_ABOUT, MF_BYCOMMAND) == (UINT)-1)
{
pMenu->InsertMenu(-1, MF_BYPOSITION|MF_ENABLED, ID_SNAPIN_ABOUT, strMenu);
}
else
{
pMenu->ModifyMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND|MF_ENABLED, ID_SNAPIN_ABOUT, strMenu);
}
}
Cleanup:
return;
Error:
pMenu->DeleteMenu(ID_HELP_SNAPINHELP, MF_BYCOMMAND);
pMenu->DeleteMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND);
goto Cleanup;
}
#ifdef IMPLEMENT_LIST_SAVE // See nodemgr.idl (t-dmarm)
/*
* Displays errors from the list save function and cleans up the file if necessary
*/
void CAMCView::ListSaveErrorMes(EListSaveErrorType etype, HANDLE hfile, LPCTSTR lpFileName)
{
CString strMessage;
switch (etype)
{
case LSaveCantCreate:
//"ERROR: Unable to create file."
FormatString1 (strMessage, IDS_LISTSAVE_ER1, lpFileName);
break;
case LSaveCantWrite:
// ERROR: Created file but encountered an error while writing to it
FormatString1 (strMessage, IDS_LISTSAVE_ER2, lpFileName);
break;
case LSaveReadOnly:
//"ERROR: File to be overwritten is read only."
FormatString1 (strMessage, IDS_LISTSAVE_ER3, lpFileName);
break;
default:
// Should not make it here
ASSERT(0);
}
MMCMessageBox (strMessage);
}
// Saves a list and performs necessary dialog boxes and error checking
SC CAMCView::ScSaveList()
{
DECLARE_SC(sc, _T("ScSaveList"));
AFX_MANAGE_STATE (AfxGetAppModuleState());
sc = ScExportListWorker();
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScGetExportListFile
//
// Synopsis: Get the filename, flags for save list.
//
// Arguments: [strFileName] - File Name retval.
// [bUnicode] - Unicode or ansi.
// [bTabDelimited] - Tab or Comma delimited.
// [bSelectedRowsOnly] - selected items only or all items.
//
// Returns: SC, S_FALSE if user cancels dialog.
//
//--------------------------------------------------------------------
SC CAMCView::ScGetExportListFile (CString& strFileName,
bool& bUnicode,
bool& bTabDelimited,
bool& bSelectedRowsOnly)
{
DECLARE_SC(sc, _T("CAMCView::ScGetExportListFile"));
CString strFilter;
LoadString(strFilter, IDS_ANSI_FILE_TYPE);
#ifdef UNICODE
{ // limit the lifetime of strUniFilter
CString strUniFilter;
LoadString(strUniFilter, IDS_UNICODE_FILE_TYPE);
strFilter += strUniFilter;
}
#endif
// End of Filter char
strFilter += "|";
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
if (sc)
return sc;
// See if there are any items selected else disable the "Selected items only" check-box.
CListCtrl& ctlList = m_pListCtrl->GetListCtrl();
int iItem = ctlList.GetNextItem( -1,LVNI_SELECTED);
bool bSomeRowSelected = (-1 != iItem);
// Create the dialog. File extensions are not localized.
CSaveFileDialog dlgFile(false, _T("txt"), NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ENABLESIZING,
strFilter, bSomeRowSelected);
// Display the dialog
if (dlgFile.DoModal() == IDCANCEL)
return S_FALSE; // S_FALSE if user cancels dialog.
// Create a wait cursor and redraw the screen (necessary in saving big files)
CWaitCursor wait;
AfxGetMainWnd()->RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW );
// Retrieve the filename
strFileName = dlgFile.GetPathName();
bSelectedRowsOnly = (dlgFile.Getflags() & SELECTED);
switch (dlgFile.GetFileType())
{
case FILE_ANSI_TEXT:
bTabDelimited = true; // Tab delimited.
bUnicode = false;
break;
case FILE_ANSI_CSV:
bTabDelimited = false; // Comma delimited.
bUnicode = false;
break;
#ifdef UNICODE
case FILE_UNICODE_TEXT:
bTabDelimited = true; // tab delimited.
bUnicode = true;
break;
case FILE_UNICODE_CSV:
bTabDelimited = false; // comma delimited.
bUnicode = true;
break;
#endif
default:
sc = E_UNEXPECTED;
break;
}
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScCreateExportListFile
//
// Synopsis: Create a file with given name & path. Write unicode marker if needed.
//
// Arguments: [strFileName] - file to create.
// [bUnicode] - unicode or ansi file.
// [bShowErrorDialogs] - Show error dialogs or not.
// [hFile] - Retval, handle to file.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScCreateExportListFile(const CString& strFileName, bool bUnicode,
bool bShowErrorDialogs, HANDLE& hFile)
{
DECLARE_SC(sc, _T("CAMCView::ScCreateExportListFile"));
// Create a file according to specs
hFile = CreateFile(strFileName, GENERIC_WRITE,
0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwAttrib = GetFileAttributes(strFileName);
// If it did not fail and the file is read-only
// Not required. Used to determine if the file being overwritten is read only and display appropriate message
if ((dwAttrib != 0xFFFFFFFF) &&
(dwAttrib & FILE_ATTRIBUTE_READONLY))
{
if (bShowErrorDialogs)
ListSaveErrorMes(LSaveReadOnly, hFile, strFileName);
return (sc = E_FAIL);
}
// Creation failed
if (hFile == INVALID_HANDLE_VALUE)
{
if (bShowErrorDialogs)
ListSaveErrorMes(LSaveCantCreate, NULL, strFileName);
sc.FromWin32(::GetLastError());
return sc;
}
/*
* for Unicode files, write the Unicode prefix
*/
if (bUnicode)
{
const WCHAR chPrefix = 0xFEFF;
const DWORD cbToWrite = sizeof (chPrefix);
DWORD cbWritten;
if (!WriteFile (hFile, &chPrefix, cbToWrite, &cbWritten, NULL) ||
(cbToWrite != cbWritten))
{
CloseHandle(hFile);
DeleteFile( strFileName );
if (bShowErrorDialogs)
ListSaveErrorMes(LSaveCantWrite, hFile, strFileName);
return (sc = E_FAIL);
}
}
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScExportListWorker
//
// Synopsis: Prompt for a file name & write the ListView data to it.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScExportListWorker()
{
DECLARE_SC(sc, _T("CAMCView::ScExportListWorker"));
CString strFileName;
bool bUnicode = false;
bool bTabDelimited = false;
bool bSelectedRowsOnly = false;
sc = ScGetExportListFile(strFileName, bUnicode, bTabDelimited, bSelectedRowsOnly);
if (sc.ToHr() == S_FALSE) // if user cancels dialog.
return sc;
sc = ScWriteExportListData(strFileName, bUnicode, bTabDelimited, bSelectedRowsOnly);
if (sc)
return sc;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScWriteExportListData
//
// Synopsis: Write ListView data to given file.
//
// Arguments: [strFileName] - File to create & write to.
// [bUnicode] - Unicode or ansi.
// [bTabDelimited] - Tab or Comma separated values.
// [bSelectedRowsOnly] - like Selected rows only.
// [bShowErrorDialogs] - Show error dialogs or not.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScWriteExportListData (const CString& strFileName,
bool bUnicode,
bool bTabDelimited,
bool bSelectedRowsOnly,
bool bShowErrorDialogs /*true*/)
{
DECLARE_SC(sc, _T("CAMCView::ScWriteExportListData"));
// Get number of rows and columns
const int cRows = m_pListCtrl->GetItemCount();
const int cCols = m_pListCtrl->GetColCount();
// If there are no columns inserted then there cannot be any
// items inserted into the listview. So error out.
if (cCols <= 0)
return (sc = E_UNEXPECTED);
HANDLE hFile = NULL;
sc = ScCreateExportListFile(strFileName, bUnicode, bShowErrorDialogs, hFile);
if (sc)
return sc;
// Retrieve the flags
CString strEol( _T("\r\n") );
LPCTSTR pszSeparator = _T("\t");
if (!bTabDelimited)
pszSeparator = _T(",");
// Determine how many columns must be printed
int printcols = 1;
struct ColInfo
{
CString strColName;
BOOL bHidden;
};
ColInfo* rgColumns = NULL;
int* pnColOrder = NULL;
// If it is LVS_REPORT, get the list of column names, order
// and hidden or not flag.
if ( (m_pListCtrl->GetViewMode() == LVS_REPORT) ||
(m_pListCtrl->GetViewMode() == MMCLV_VIEWSTYLE_FILTERED) )
{
printcols = cCols;
// Allocate mem to store col names, order, hidden states
rgColumns = new ColInfo[printcols];
if (! rgColumns)
{
sc = E_OUTOFMEMORY;
goto Error;
}
pnColOrder = new int[printcols];
if (! pnColOrder)
{
sc = E_OUTOFMEMORY;
goto Error;
}
CHeaderCtrl* pHeader = m_pListCtrl->GetHeaderCtrl();
sc = ScCheckPointers(pHeader, E_UNEXPECTED);
if (sc)
goto Error;
// Get the order
if (!Header_GetOrderArray(pHeader->GetSafeHwnd(), printcols, pnColOrder))
{
goto Error;
}
// Get the name and hidden state of cols
for (int i = 0; i < printcols ; i++)
{
TCHAR szColName[MAX_PATH * 2];
HDITEM hdItem;
hdItem.mask = HDI_TEXT | HDI_LPARAM;
hdItem.pszText = szColName;
hdItem.cchTextMax = countof (szColName);
if (pHeader->GetItem (i, &hdItem))
{
CHiddenColumnInfo hci (hdItem.lParam);
rgColumns[i].strColName = hdItem.pszText;
rgColumns[i].bHidden = hci.fHidden;
}
else
{
goto Error;
}
}
for (int i = 0; i < printcols ; i++)
{
// Print the column name according to the order
if (rgColumns[pnColOrder[i]].bHidden)
continue;
if ( (!Write2File(hFile, rgColumns[pnColOrder[i]].strColName, bUnicode)) ||
((i < printcols - 1) && (!Write2File(hFile, pszSeparator, bUnicode))))
{
goto CantWriteError;
}
}
// Write an EOL character if necessary
if (!Write2File(hFile, strEol, bUnicode))
{
goto CantWriteError;
}
}
{
// Data for use in the writing stage
CString strData;
CListCtrl& ctlList = m_pListCtrl->GetListCtrl();
// Set iNextType to 0 if all items will be saved or LVNI_SELECTED if only selected ones will be saved
int iNextType = 0;
if (bSelectedRowsOnly)
iNextType = LVNI_SELECTED;
// Find the first item in the list
int iItem = ctlList.GetNextItem( -1,iNextType);
// Iterate until there are no more items to save
while (iItem != -1)
{
for(int ind2 = 0; ind2 < printcols ; ind2++)
{
if (rgColumns)
{
// If not hidden get the item
if (rgColumns[pnColOrder[ind2]].bHidden)
continue;
else
strData = ctlList.GetItemText( iItem, pnColOrder[ind2]);
}
else
strData = ctlList.GetItemText( iItem, ind2);
// Write the text and if necessary a comma
// If either one fails, then delete the file and return
if ( (!Write2File(hFile, strData, bUnicode)) ||
((ind2 < printcols - 1) && (!Write2File(hFile, pszSeparator, bUnicode))))
{
goto CantWriteError;
}
}
// Write an EOL character if necessary
if (!Write2File(hFile, strEol, bUnicode))
{
goto CantWriteError;
}
// Find the next item to save
iItem = ctlList.GetNextItem( iItem, iNextType);
}
}
Cleanup:
if (rgColumns)
delete[] rgColumns;
if (pnColOrder)
delete[] pnColOrder;
CloseHandle(hFile);
return (sc);
CantWriteError:
if (bShowErrorDialogs)
ListSaveErrorMes(LSaveCantWrite, hFile, strFileName);
Error:
DeleteFile( strFileName );
goto Cleanup;
}
// Write out a string to the given file
// Used as a separate function to preserve memory
// Returns true if successful, false otherwise
bool CAMCView::Write2File(HANDLE hfile, LPCTSTR strwrite, BOOL fUnicode)
{
DECLARE_SC(sc, TEXT("CAMCView::Write2File"));
// parameter check;
sc = ScCheckPointers( strwrite );
if (sc)
return false;
// Initializes Macro
USES_CONVERSION;
// The number of bytes written
DWORD cbWritten;
DWORD cbToWrite;
if (fUnicode)
{
// Convert the string to Unicode and write it to hfile
LPCWSTR Ustring = T2CW( strwrite );
cbToWrite = wcslen (Ustring) * sizeof (WCHAR);
WriteFile(hfile, Ustring, cbToWrite, &cbWritten, NULL);
}
else
{
// Convert the string to ANSI and write it to hfile
const unsigned char* Astring = (const unsigned char*) T2CA( strwrite );
cbToWrite = _mbsnbcnt (Astring, _mbslen (Astring));
WriteFile(hfile, Astring, cbToWrite, &cbWritten, NULL);
}
// Make sure that the correct number of bytes were written
return (cbWritten == cbToWrite);
}
#endif // IMPLEMENT_LIST_SAVE See nodemgr.idl (t-dmarm)
// Refreshes all panes and HTML
void CAMCView::OnRefresh()
{
HWND hwnd = ::GetFocus();
if (IsVerbEnabled(MMC_VERB_REFRESH))
{
ScConsoleVerb(evRefresh);
}
else if (HasWebBrowser())
{
ScWebCommand(eWeb_Refresh);
}
::SetFocus(hwnd);
}
void CAMCView::OnVerbAccelKey(UINT nID)
{
DECLARE_SC(sc, TEXT("CAMCView::OnVerbAccelKey"));
switch (nID)
{
case ID_MMC_CUT:
if (IsVerbEnabled(MMC_VERB_CUT))
sc = ScConsoleVerb(evCut);
break;
case ID_MMC_COPY:
if (IsVerbEnabled(MMC_VERB_COPY))
sc = ScConsoleVerb(evCopy);
break;
case ID_MMC_PASTE:
if (IsVerbEnabled(MMC_VERB_PASTE))
{
// Check if the dataobject in clipboard can be
// pasted into the selected node.
// Then only we send MMCN_PASTE notification to snapin.
HNODE hNode = NULL;
LPARAM lvData = NULL;
bool bScope = FALSE;
sc = ScGetFocusedItem(hNode, lvData, bScope);
if (sc)
break;
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(pNC, hNode, E_UNEXPECTED);
if (sc)
break;
bool bPasteAllowed = false;
sc = pNC->QueryPasteFromClipboard(hNode, bScope, lvData, bPasteAllowed);
if (sc)
break;
if (bPasteAllowed)
sc = ScConsoleVerb(evPaste);
}
break;
case ID_MMC_PRINT:
if (IsVerbEnabled(MMC_VERB_PRINT))
sc = ScConsoleVerb(evPrint);
break;
case ID_MMC_RENAME:
if (IsVerbEnabled(MMC_VERB_RENAME))
sc = ScConsoleVerb(evRename);
break;
case ID_MMC_REFRESH:
OnRefresh();
break;
default:
ASSERT(FALSE);
}
if (sc)
return;
}
//
// Handle accelerator keys shared by result and scope panes
//
BOOL CAMCView::OnSharedKeyDown(WORD wVKey)
{
BOOL bReturn = TRUE;
if (::GetKeyState(VK_CONTROL) < 0)
{
switch (wVKey)
{
case 'C':
case 'c':
case VK_INSERT:
OnVerbAccelKey(ID_MMC_COPY); // Ctrl-C, Ctrl-Insert
break;
case 'V':
case 'v':
OnVerbAccelKey(ID_MMC_PASTE); // Ctrl-V
break;
case 'X':
case 'x':
OnVerbAccelKey(ID_MMC_CUT); // Ctrl-X
break;
default:
bReturn = FALSE;
}
}
else if (::GetKeyState(VK_SHIFT) < 0)
{
switch (wVKey)
{
case VK_DELETE:
OnVerbAccelKey(ID_MMC_CUT); // Shift-Delete
break;
case VK_INSERT:
OnVerbAccelKey(ID_MMC_PASTE); // Shift -Insert
break;
default:
bReturn = FALSE;
}
}
else
{
switch (wVKey)
{
case VK_F2:
OnVerbAccelKey(ID_MMC_RENAME); // F2
break;
default:
bReturn = FALSE;
}
}
return bReturn;
}
//+-------------------------------------------------------------------
//
// Member: ScConsoleVerb
//
// Synopsis: Execute the Console verb.
//
// Arguments: [nVerb] - The verb to be executed.
//
// Note: The verb is executed in the context of
// currently focused item (scope or result).
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScConsoleVerb (int nVerb)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
ASSERT_VALID (this);
DECLARE_SC (sc, _T("CAMCView::ScConsoleVerb"));
HNODE hNode = NULL;
LPARAM lvData = 0;
bool bScope = false;
// Get the focused item to process the console verb.
sc = ScGetFocusedItem(hNode, lvData, bScope);
if (sc)
return sc;
sc = ScProcessConsoleVerb(hNode, bScope, lvData, nVerb);
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: ScProcessConsoleVerb
//
// Synopsis: Execute the Console verb with given context.
//
// Arguments: [hNode] - The tree node context.
// [bScope] - Scope or Result pane.
// [lvData] - LPARAM of result item (if result pane has focus).
// [nVerb] - The verb to be executed.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScProcessConsoleVerb(HNODE hNode, bool bScope, LPARAM lvData, int nVerb)
{
DECLARE_SC (sc, _T("CAMCView::ScProcessConsoleVerb"));
AFX_MANAGE_STATE (AfxGetAppModuleState());
ASSERT_VALID (this);
// To maintain compatibility with MMC1.2 (This is init to LVERROR which
// nodemgr process differently).
if (bScope)
lvData = 0;
if (lvData == LVDATA_BACKGROUND)
{
switch (nVerb)
{
case evCut:
case evCopy:
case evDelete:
case evRename:
sc = E_UNEXPECTED;
return sc;
}
}
NCLBK_NOTIFY_TYPE nclbk = NCLBK_NONE;
switch (nVerb)
{
case evCut: nclbk = NCLBK_CUT; break;
case evCopy: nclbk = NCLBK_COPY; break;
case evDelete: nclbk = NCLBK_DELETE; break;
case evProperties: nclbk = NCLBK_PROPERTIES; break;
case evPrint: nclbk = NCLBK_PRINT; break;
case evPaste:
{
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(pNC, E_UNEXPECTED);
if (sc)
return sc;
sc = pNC->Paste(hNode, bScope, lvData);
if (sc)
return sc;
sc = ScPaste ();
if (sc)
return sc;
break;
}
case evRefresh:
// if web page on view, send it a refresh first
if (HasWebBrowser())
sc = ScWebCommand(eWeb_Refresh);
if (sc)
return sc;
nclbk = NCLBK_REFRESH;
break;
case evRename:
// Enable edit for the item.
if (bScope == TRUE)
{
if (sc = ScCheckPointers(m_pTreeCtrl, E_UNEXPECTED))
return sc;
HTREEITEM hti = m_pTreeCtrl->GetSelectedItem();
if (sc = ScCheckPointers(hti, E_UNEXPECTED))
return sc;
m_pTreeCtrl->EditLabel(hti);
}
else
{
if ( sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED))
return sc;
CAMCListView* pListView = m_pListCtrl->GetListViewPtr();
if (NULL == pListView)
{
sc = E_UNEXPECTED;
return sc;
}
int iItem = _GetLVSelectedItemData(&lvData);
ASSERT(iItem >= 0);
CListCtrl& listCtrl = pListView->GetListCtrl();
listCtrl.EditLabel(iItem);
}
break;
default:
sc = E_UNEXPECTED;
return sc;
}
if (nclbk != NCLBK_NONE)
{
// Ask the nodemgr to process the verb.
INodeCallback* pNC = GetNodeCallback();
if (pNC == NULL)
{
sc = E_UNEXPECTED;
return sc;
}
sc = pNC->Notify(hNode, nclbk, bScope, lvData);
if (sc)
return sc;
}
if (nclbk == NCLBK_CUT)
sc = ScCut (bScope ? m_pTreeCtrl->GetSelectedItem() : 0);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScListViewSelectionActivate
//
// Synopsis: Only the list(/Web/OCX) or the tree can be "active" from the point
// of view of selected items and MMCN_SELECT. This is not
// the same as the MFC concept of "active view". There are a couple
// of views that cannot be active in this sense, such as the taskpad
// and tab views.
// When the active view (according to this definition) changes, this
// function is called. Thus, ScTreeViewSelectionActivate and
// ScListViewSelectionActivate/ScSpecialResultpaneSelectionActivate
// are always called in pairs when the activation changes, one to handle
// deactivation, and one to handle activation.
//
// Consider the following scenario
// 1) The tree view has (MFC/windows style) focus.
// 2) The user clicks on the taskpad view
// Result - selection activation does not change from the tree. All verbs
// still correspond to the selected tree item.
// 3) The user clicks on the folder view
// Result - once again, selection activation does not chang
// 4) The user clicks on one of the result views eg the list
// Result - ScTreeViewSelectionActivate(false) and ScListViewSelectionActivate(true)
// Thus verbs and the toolbar now correspond to the selected list item(s).
// 5) The user clicks on the taskpad view.
// Result - as in step 2, nothing happens
// 6) The user clicks on the result view
// Result - because the active view has not changed, nothing happens.
//
// Arguments: [bActivate] - [in]
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScListViewSelectionActivate(bool bActivate)
{
DECLARE_SC(sc, TEXT("CAMCView::ScListViewSelectionActivate"));
if (m_pListCtrl == NULL)
return sc;
INodeCallback* pNC = GetNodeCallback();
sc = ScCheckPointers(pNC, E_UNEXPECTED);
if (sc)
{
sc.TraceAndClear();
return sc;
}
HNODE hNodeSel = GetSelectedNode();
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = FALSE;
selInfo.m_bDueToFocusChange = TRUE;
#ifdef DBG
if (bActivate == TRUE)
{
ASSERT(m_bProcessMultiSelectionChanges == false);
}
#endif // DBG
/*
* The below block can never execute. When m_bProcessMultiSelectionChanges is
* set to true messages are posted to handle multiselection changes. So the
* handler OnProcessMultiSelectionChanges should have processed the message and the
* m_bProcessMultiSelectionChanges should have been reset by now. If there is
* some unknown way to make de-activate the listview before processing the message
* then below block will be executed that will send de-select notification.
*
* The below block sends a de-select multi-select items.
*/
if (m_bProcessMultiSelectionChanges)
{
ASSERT(false); // Would like to know when this block is hit.
ASSERT(bActivate == false);
m_bProcessMultiSelectionChanges = false;
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
// Focus change so appropriately enable std-toolbar buttons
// back, forward, export-list, up-one-level, show/hide-scope, help
sc = ScUpdateStandardbarMMCButtons();
if (sc)
sc.TraceAndClear();
}
bool bSelect = bActivate;
do
{
//
// Multi select
//
int cSelected = m_pListCtrl->GetSelectedCount();
if (cSelected > 1)
{
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, bSelect, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
m_bLastSelWasMultiSel = bSelect;
break;
}
//
// Zero or Single select
//
if (cSelected == 0)
{
selInfo.m_bBackground = TRUE;
selInfo.m_lCookie = LVDATA_BACKGROUND;
}
else
{
#include "pushwarn.h"
#pragma warning(disable: 4552) // ">=" operator has no effect
VERIFY(_GetLVSelectedItemData(&selInfo.m_lCookie) >= 0);
#include "popwarn.h"
}
ASSERT(cSelected >= 0);
ASSERT(cSelected <= 1);
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, bSelect, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
} while (0);
return sc;
}
void CAMCView::OnShowWindow(BOOL bShow, UINT nStatus)
{
CView::OnShowWindow(bShow, nStatus);
}
int CAMCView::_GetLVItemData(LPARAM *plParam, UINT flags)
{
HWND hwnd = m_pListCtrl->GetListViewHWND();
int iItem = ::SendMessage(hwnd, LVM_GETNEXTITEM, (WPARAM) (int) -1,
MAKELPARAM(flags, 0));
if (iItem >= 0)
{
if (IsVirtualList())
{
*plParam = iItem;
}
else
{
LV_ITEM lvi;
ZeroMemory(&lvi, sizeof(lvi));
lvi.iItem = iItem;
lvi.mask = LVIF_PARAM;
#include "pushwarn.h"
#pragma warning(disable: 4553) // "==" operator has no effect
VERIFY(::SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&lvi) == TRUE);
#include "popwarn.h"
*plParam = lvi.lParam;
}
}
return iItem;
}
int CAMCView::_GetLVFocusedItemData(LPARAM *plParam)
{
return (_GetLVItemData (plParam, LVNI_FOCUSED));
}
int CAMCView::_GetLVSelectedItemData(LPARAM *plParam)
{
return (_GetLVItemData (plParam, LVNI_SELECTED));
}
void CAMCView::SetListViewMultiSelect(BOOL bMultiSelect)
{
long lStyle = m_pListCtrl->GetListStyle();
if (bMultiSelect == FALSE)
lStyle |= LVS_SINGLESEL;
else
lStyle &= ~LVS_SINGLESEL;
m_pListCtrl->SetListStyle(lStyle);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnItemDeselected
*
* PURPOSE: Tree observer method. Called when a tree item is deselected.
*
* PARAMETERS:
* HNODE hNode : The node that was deselected.
*
* NOTE: This function can be merged with the next.
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnItemDeselected(HNODE hNode)
{
DECLARE_SC (sc, TEXT("CAMCView::ScOnItemDeselected"));
DeSelectResultPane(hNode);
if (!hNode)
return sc;
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
// Ask the SnapIn to cleanup any items it has inserted.
INodeCallback* spNodeCallBack = GetNodeCallback();
ASSERT(spNodeCallBack != NULL);
selInfo.m_bScope = TRUE;
selInfo.m_pView = NULL;
Dbg(DEB_USER6, _T("T1. CAMCTreeView::OnDeSelectNode<1, 0>\n"));
sc = ScNotifySelect (spNodeCallBack, hNode, false /*fMultiSelect*/, false, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::DeSelectResultPane
*
* PURPOSE: Deselects the result pane and sets the view type to invalid.
*
* PARAMETERS:
* HNODE hNodeSel :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CAMCView::DeSelectResultPane(HNODE hNodeSel)
{
DECLARE_SC(sc, TEXT("CAMCView::DeSelectResultPane"));
if (m_spTaskPadHost.GetInterfacePtr() != NULL)
{
CTaskPadHost *pTaskPadHost = dynamic_cast<CTaskPadHost *>(m_spTaskPadHost.GetInterfacePtr());
m_spTaskPadHost = NULL;
}
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
if (hNodeSel == 0)
return;
// If there was no list view being displayed return.
if (HasListOrListPad())
{
// if we were in ListPad-mode, undo that.
if (m_pListCtrl->IsListPad())
{
sc = m_pListCtrl->ScAttachToListPad (NULL, NULL);
if(sc)
sc.TraceAndClear(); //ignore
}
// If we are in edit mode cancel it.
m_pListCtrl->GetListCtrl().EditLabel(-1);
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = FALSE;
/*
* The below block can never execute. When m_bProcessMultiSelectionChanges is
* set to true messages are posted to handle multiselection changes. So the
* handler OnProcessMultiSelectionChanges should have processed the message and the
* m_bProcessMultiSelectionChanges should have been reset by now. If there is
* some unknown way to make select different node (to deselect result pane)
* before processing the message then below block will be executed that will
* send de-select notification.
*
* The below block sends a de-select multi-select items.
*/
if (m_bProcessMultiSelectionChanges)
{
ASSERT(false); // Would like to know when this block is hit.
m_bProcessMultiSelectionChanges = false;
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
else
{
UINT cSel = m_pListCtrl->GetSelectedCount();
if (cSel == 1)
{
if (cSel)
{
int iItem = _GetLVSelectedItemData(&selInfo.m_lCookie);
ASSERT(iItem != -1);
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, false, &selInfo);
if (sc)
sc.TraceAndClear(); // ignore & continue;
}
}
else if (cSel > 1)
{
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
if (sc)
sc.TraceAndClear(); // ignore & continue;
m_bLastSelWasMultiSel = false;
}
}
}
else
{
// If it is OCX or Web send de-select notifications.
sc = ScSpecialResultpaneSelectionActivate(FALSE);
}
}
LRESULT CAMCView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// NATHAN
case WM_NOTIFYFORMAT:
{
int id = ::GetDlgCtrlID ((HWND)wParam);
//if (m_pTreeCtrl == NULL || ((HWND)wParam != m_pTreeCtrl->m_hWnd))
if (id == IDC_ListView)
return NFR_UNICODE;
}
break;
#ifdef DBG
case WM_KEYUP:
{
switch (wParam)
{
case VK_SHIFT:
case VK_CONTROL:
// We removed some code that will work if m_bProcessMultiSelectionChanges
// is true. I dont see any way the bool being true. Still let us have below
// assert. If this gets fired then we should call OnProcessMultiSelectionChanges.
ASSERT(m_bProcessMultiSelectionChanges == false);
break;
}
break;
}
break;
#endif
}
return CView::WindowProc(message, wParam, lParam);
}
/*+-------------------------------------------------------------------------*
* CAMCView::ChangePane
*
* Moves the activation from pane to pane. The (forward) tab order is
*
* Scope pane (either tree or favorites)
* Result pane
* Task view (if visible)
*--------------------------------------------------------------------------*/
class CTabOrderEntry
{
public:
CView* const m_pView;
const bool m_bValid; // is this entry valid
CTabOrderEntry(CView *pView)
: m_pView (pView),
m_bValid ((pView != NULL) && IsWindowVisible (pView->m_hWnd))
{}
};
void CAMCView::ChangePane(AMCNavDir eDir)
{
ASSERT_VALID (this);
CFrameWnd* pFrame = GetParentFrame();
CView* pActiveView = pFrame->GetActiveView();
HWND hWndActive = ::GetFocus();
CTabOrderEntry rgOrderEntry[] =
{
CTabOrderEntry(GetPaneView(ePane_ScopeTree)), // tree has focus
CTabOrderEntry(GetPaneView(ePane_Results)), // results has focus - note the value of INDEX_RESULTS_PANE below.
CTabOrderEntry(m_pViewExtensionCtrl), // view extension web page has focus
CTabOrderEntry(m_pResultFolderTabView), // result tab control has focus
};
/*
* this is the index of the result pane entry in rgOrderEntry,
* used for default focus placement if something unexpected happens
*/
const int INDEX_RESULTS_PANE = 1;
ASSERT (rgOrderEntry[INDEX_RESULTS_PANE].m_pView == GetPaneView(ePane_Results));
// Get the navigator if one exists. If so, use it and bail.
CAMCNavigator* pNav = dynamic_cast<CAMCNavigator*>(pActiveView);
if (pNav && pNav->ChangePane(eDir))
return;
int cEntries = (sizeof(rgOrderEntry) / sizeof(rgOrderEntry[0]));
// get the currently active entry.
for(int i = 0; i< cEntries; i++)
{
if( (rgOrderEntry[i].m_pView == pActiveView) )
break;
}
ASSERT(i < cEntries);
if(i>= cEntries)
{
// if we don't know where we are, a bit of defensive coding puts the focus back
// on the results pane, ie into a known state.
i = INDEX_RESULTS_PANE;
}
int iPrev = i;
// at this point we've found the right entry.
int increment = (eDir==AMCNAV_PREV) ? -1 : 1;
int sanityCount = 0;
while(true)
{
i = (i+increment+cEntries) % cEntries;
if(rgOrderEntry[i].m_bValid)
break;
sanityCount++;
if(sanityCount == cEntries)
{
ASSERT(0 && "Something's seriously messed up!!");
return;
}
}
// update the active view
if (i != iPrev)
pFrame->SetActiveView(rgOrderEntry[i].m_pView);
else
{
// if view retains focus and has a navigator,
// tell navigator to take the focus
if (pNav)
pNav->TakeFocus(eDir);
}
// if there is a special focus handler, call it.
CFocusHandler *pFocusHandler = dynamic_cast<CFocusHandler *>(rgOrderEntry[i].m_pView);
if(pFocusHandler != NULL)
{
pFocusHandler->OnKeyboardFocus (LVIS_FOCUSED | LVIS_SELECTED,
LVIS_FOCUSED | LVIS_SELECTED);
}
}
void CAMCView::OnNextPane()
{
ChangePane(AMCNAV_NEXT);
}
void CAMCView::OnPrevPane()
{
ChangePane(AMCNAV_PREV);
}
void CAMCView::OnUpdateNextPane(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
}
void CAMCView::OnUpdatePrevPane(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
}
void RestrictPointToWindow (CWnd* pwnd, CPoint* ppt)
{
CRect rectWnd;
pwnd->GetClientRect (rectWnd);
if (ppt->x < rectWnd.left)
ppt->x = rectWnd.left;
else if (ppt->x > rectWnd.right)
ppt->x = rectWnd.right;
if (ppt->y < rectWnd.top)
ppt->y = rectWnd.top;
else if (ppt->y > rectWnd.bottom)
ppt->y = rectWnd.bottom;
}
void CAMCView::OnShiftF10()
{
CRect rect;
CWnd* pwndFocus = GetFocus();
CListCtrl& lc = m_pListCtrl->GetListCtrl();
ASSERT_VALID (this);
if (pwndFocus == &lc)
{
int iItem = lc.GetNextItem (-1, LVNI_SELECTED);
CPoint pt = 0;
if (iItem != -1)
{
VERIFY (lc.GetItemRect (iItem, rect, LVIR_ICON));
pt = rect.CenterPoint ();
}
else
{
CHeaderCtrl* pHeader = m_pListCtrl->GetHeaderCtrl();
if (pHeader != NULL && pHeader->IsWindowVisible())
{
pHeader->GetClientRect(&rect);
pt.y = rect.Height();
ASSERT (pt.y >= 0);
}
}
/*
* make sure the context menu doesn't show up outside the window
*/
RestrictPointToWindow (&lc, &pt);
m_pListCtrl->GetListViewPtr()->ClientToScreen(&pt);
OnListContextMenu(pt);
}
else if (pwndFocus == m_pTreeCtrl)
{
HTREEITEM hTreeItem = m_pTreeCtrl->GetSelectedItem();
if (hTreeItem == NULL)
return;
m_pTreeCtrl->GetItemRect (hTreeItem, rect, TRUE);
CPoint ptClient (rect.left, rect.bottom-1);
/*
* make sure the context menu doesn't show up outside the window
*/
RestrictPointToWindow (m_pTreeCtrl, &ptClient);
CPoint ptScreen = ptClient;
m_pTreeCtrl->ClientToScreen(&ptScreen);
OnTreeContextMenu(ptScreen, ptClient, hTreeItem);
}
}
void CAMCView::OnUpdateShiftF10(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
}
BOOL CAMCView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT && pWnd == this && !IsTracking())
{
CPoint pt (GetMessagePos());
ScreenToClient (&pt);
if (m_rectVSplitter.PtInRect (pt))
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
return TRUE;
}
}
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
SC CAMCView::ScCut (HTREEITEM htiCut)
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC (sc, _T("CAMCView::ScCut"));
CMainFrame* pMain = AMCGetMainWnd();
sc = ScCheckPointers (pMain, E_UNEXPECTED);
if (sc)
return (sc);
pMain->SetWindowToNotifyCBChange(m_hWnd);
if (htiCut)
m_pTreeCtrl->SetItemState (htiCut, TVIS_CUT, TVIS_CUT);
else
m_pListCtrl->CutSelectedItems (TRUE);
m_htiCut = htiCut;
return (S_OK);
}
SC CAMCView::ScPaste ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
DECLARE_SC (sc, _T("CAMCView::ScPaste"));
if (!m_htiCut)
m_pListCtrl->CutSelectedItems(FALSE);
CMainFrame* pMain = AMCGetMainWnd();
sc = ScCheckPointers (pMain, E_UNEXPECTED);
if (sc)
return (sc);
pMain->SetWindowToNotifyCBChange(NULL);
return (S_OK);
}
HRESULT CAMCView::SendGenericNotify(NCLBK_NOTIFY_TYPE nclbk)
{
BOOL bScope = TRUE;
MMC_COOKIE lCookie = 0;
int iItem = -1;
ASSERT_VALID (this);
if (m_pListCtrl && m_pListCtrl->GetListViewHWND() == ::GetFocus())
{
iItem = _GetLVSelectedItemData(&lCookie);
if (iItem != -1)
bScope = FALSE;
}
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
if (pNC == NULL)
return E_FAIL;
HNODE hNodeSel = GetSelectedNode();
ASSERT(hNodeSel != NULL);
if (hNodeSel == NULL)
return E_FAIL;
// selection notifications should use ScNotifySelect()
ASSERT ((nclbk != NCLBK_SELECT) && (nclbk != NCLBK_MULTI_SELECT));
return pNC->Notify(hNodeSel, nclbk, bScope, lCookie);
}
void CAMCView::SaveStartingSelectedNode()
{
m_htiStartingSelectedNode = m_pTreeCtrl->GetSelectedItem();
}
bool CAMCView::HasNodeSelChanged()
{
return (m_pTreeCtrl->GetSelectedItem() != m_htiStartingSelectedNode);
}
//+---------------------------------------------------------------------------
//
// Function: OnSysKeyDown
//
// Synopsis: Handles WM_SYSKEYDOWN message.
// CAMCTreeView::OnSysKeyDown handles the Tree view so
// here we handle only the list view (or Result pane)
//
// Returns: none
//
//+---------------------------------------------------------------------------
void CAMCView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch (nChar)
{
case VK_LEFT:
ScWebCommand(eWeb_Back);
break;
case VK_RIGHT:
ScWebCommand(eWeb_Forward);
break;
}
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnAppCommand
*
* WM_APPCOMMAND handler for CAMCView. This is used to handle to forward
* and backward buttons on the IntelliMouse Explorer and the Microsoft
* Natural Keyboards
*--------------------------------------------------------------------------*/
LRESULT CAMCView::OnAppCommand(WPARAM wParam, LPARAM lParam)
{
DECLARE_SC (sc, _T("CAMCView::OnAppCommand"));
switch (GET_APPCOMMAND_LPARAM (lParam))
{
case APPCOMMAND_BROWSER_BACKWARD:
sc = ScWebCommand (eWeb_Back);
if (sc)
break;
return (TRUE); // handled here
case APPCOMMAND_BROWSER_FORWARD:
sc = ScWebCommand (eWeb_Forward);
if (sc)
break;
return (TRUE); // handled here
case APPCOMMAND_BROWSER_REFRESH:
OnRefresh ();
return (TRUE); // handled here
}
return (Default());
}
void CAMCView::OnPaletteChanged(CWnd* pwndFocus)
{
// if displaying a web page, forward the palette change to the shell
if (HasWebBrowser() && m_pWebViewCtrl != NULL)
{
if (m_pWebViewCtrl->m_hWnd != NULL)
{
HWND hwndShell = ::GetWindow(m_pWebViewCtrl->m_hWnd, GW_CHILD);
if (hwndShell != NULL)
::SendMessage(hwndShell, WM_PALETTECHANGED, (WPARAM)pwndFocus->m_hWnd, (LPARAM)0);
}
}
}
BOOL CAMCView::OnQueryNewPalette()
{
// if displaying a web page, forward the palette query to the shell
if (HasWebBrowser() && m_pWebViewCtrl != NULL)
{
if (m_pWebViewCtrl->m_hWnd != NULL)
{
HWND hwndShell = ::GetWindow(m_pWebViewCtrl->m_hWnd, GW_CHILD);
if (hwndShell != NULL)
return ::SendMessage(hwndShell, WM_QUERYNEWPALETTE, (WPARAM)0, (LPARAM)0);
}
}
return 0;
}
BOOL CAMCView::OwnsResultList(HTREEITEM hti)
{
if (hti == NULL)
return (false);
// if result list is active
if (HasListOrListPad())
{
// Get selected node and query node
HNODE hnodeSelected = GetSelectedNode();
HNODE hnode = m_pTreeCtrl ? m_pTreeCtrl->GetItemNode(hti) : NULL;
if (hnodeSelected && hnode)
{
INodeCallback* pNC = GetNodeCallback();
ASSERT(pNC != NULL);
// See if the selected node uses the query node as a target
// S_OK - yes
// S_FALSE - uses a different target node
// E_FAIL - doesn't use a target node
HRESULT hr = pNC->IsTargetNodeOf(hnodeSelected, hnode);
if (hr == S_OK)
return TRUE;
else if (hr == S_FALSE)
return FALSE;
else
return (hnodeSelected == hnode);
}
}
return FALSE;
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnSysColorChange
*
* WM_SYSCOLORCHANGE handler for CAMCView.
*--------------------------------------------------------------------------*/
void CAMCView::OnSysColorChange()
{
CView::OnSysColorChange();
/*
* the list control isn't a window but rather a wrapper on a window,
* so we need to manually forward on the WM_SYSCOLORCHANGE
*/
m_pListCtrl->OnSysColorChange();
}
/*+-------------------------------------------------------------------------*
* TrackerCallback function
*
* Called by CViewTracker when tracking of splitter bar is completed. This
* function applies the changes if the AcceptChange flag is set.
*--------------------------------------------------------------------------*/
void CALLBACK TrackerCallback(
TRACKER_INFO* pInfo,
bool bAcceptChange,
bool bSyncLayout)
{
DECLARE_SC (sc, _T("TrackerCallback"));
if (bAcceptChange)
{
CAMCView* pView = dynamic_cast<CAMCView*>(pInfo->pView);
sc = ScCheckPointers (pView, E_UNEXPECTED);
if (sc)
return;
// Set new width and recompute layout
pView->m_PaneInfo[CConsoleView::ePane_ScopeTree].cx = pInfo->rectTracker.left;
pView->SetDirty();
if (bSyncLayout)
{
Trace (tagSplitterTracking, _T("Synchronous layout"));
pView->RecalcLayout();
pView->UpdateWindow();
}
else
{
Trace (tagSplitterTracking, _T("Deferred layout"));
pView->DeferRecalcLayout();
}
}
}
/*+-------------------------------------------------------------------------*
* PtInWindow
*
* Test if point is in a window (pt is in screen coordinates)
*--------------------------------------------------------------------------*/
BOOL PtInWindow(CWnd* pWnd, CPoint pt)
{
if (!pWnd->IsWindowVisible())
return FALSE;
CRect rect;
pWnd->GetWindowRect(&rect);
return rect.PtInRect(pt);
}
/*+-------------------------------------------------------------------------*
* CAMCView::ScJiggleListViewFocus
*
* Bug 345402: Make sure the focus rect is on the list control (if it
* actually has the focus) to wake up any accessibility tools that might
* be watching for input and focus changes.
*
* We post a message here rather than doing it synchronously so we can
* allow any other processing in the list (like sorting) to happen
* before we put the focus on the 1st item. If we didn't wait until after
* the sort, the item we put the focus on might not be the first item
* in the list.
*--------------------------------------------------------------------------*/
SC CAMCView::ScJiggleListViewFocus ()
{
AFX_MANAGE_STATE (AfxGetAppModuleState());
PostMessage (m_nJiggleListViewFocusMsg);
return (S_OK);
}
LRESULT CAMCView::OnJiggleListViewFocus (WPARAM, LPARAM)
{
CAMCListView* pListView = m_pListCtrl->GetListViewPtr();
/*
* If the focus is on the list control, make sure that at least one item
* has the focus rect. Doing this will wake up any accessibility tools
* that might be watching (Bug 345402).
*/
if ((GetFocusedPane() == ePane_Results) &&
(GetResultView() == pListView))
{
pListView->OnKeyboardFocus (LVIS_FOCUSED, LVIS_FOCUSED);
}
return (0);
}
/*+-------------------------------------------------------------------------*
* CAMCView::OnDeferRecalcLayout
*
* CAMCView::m_nDeferRecalcLayoutMsg registered message handler for CAMCView.
*
* Parameters:
* bDoArrange - if non-zero need to call Arrange on list-view so that
* common-control can layout items properly.
*
*--------------------------------------------------------------------------*/
LRESULT CAMCView::OnDeferRecalcLayout (WPARAM bDoArrange, LPARAM)
{
Trace (tagLayout, _T("CAMCView::OnDeferRecalcLayout"));
RecalcLayout();
if (bDoArrange && m_pListCtrl)
{
int nViewMode = m_pListCtrl->GetViewMode();
// Arrange is only for large & small icon modes.
if ( (nViewMode == MMCLV_VIEWSTYLE_ICON) ||
(nViewMode == MMCLV_VIEWSTYLE_SMALLICON) )
m_pListCtrl->Arrange(LVA_DEFAULT);
}
return (0);
}
/*+-------------------------------------------------------------------------*
* CDeferredPageBreak
*
*
* PURPOSE: Used to delay sending a web page break until an idle timeout.
* This used to be sent via PostMessage, but resulted in multiple
* ScDoPageBreak calls on the same stack, since the latter has
* its own message loop. By using the idle timer, we guarantee that
* there are no reentrant problems.
*
*+-------------------------------------------------------------------------*/
class CDeferredPageBreak : public CIdleTask
{
public:
CDeferredPageBreak(UINT nAddPageBreakAndNavigateMsg, HWND hWnd, WPARAM wParam, LPCTSTR szURL) :
m_atomTask (AddAtom (_T("CDeferredPageBreak"))),
m_nAddPageBreakAndNavigateMsg(nAddPageBreakAndNavigateMsg),
m_hWnd(hWnd),
m_wParam(wParam),
m_strURL(szURL ? szURL : _T(""))
{
}
~CDeferredPageBreak() {}
// IIdleTask methods
SC ScDoWork()
{
DECLARE_SC (sc, TEXT("CDeferredPageBreak::ScDoWork"));
::SendMessage(m_hWnd, m_nAddPageBreakAndNavigateMsg, m_wParam,
reinterpret_cast<LPARAM>( m_strURL.data() )); // do this synchronously
return sc;
}
SC ScGetTaskID(ATOM* pID)
{
DECLARE_SC (sc, TEXT("CDeferredPageBreak::ScGetTaskID"));
sc = ScCheckPointers(pID);
if(sc)
return sc;
*pID = m_atomTask;
return sc;
}
SC ScMerge(CIdleTask* pitMergeFrom) {return S_FALSE /*do not merge*/;}
private:
const ATOM m_atomTask;
const UINT m_nAddPageBreakAndNavigateMsg;
const HWND m_hWnd;
const WPARAM m_wParam;
const tstring m_strURL;
};
/*+-------------------------------------------------------------------------*
* CAMCView::ScAddPageBreakAndNavigate
*
* Adds a page break to the history list. This needs to occur asynchronously,
* so we post a private message to ourselves and return.
*--------------------------------------------------------------------------*/
SC CAMCView::ScAddPageBreakAndNavigate (bool fAddPageBreak, bool fNavigate, LPCTSTR szURL)
{
AFX_MANAGE_STATE (AfxGetAppModuleState()); // not sure if we need this, but doesn't hurt to have it in here.
DECLARE_SC (sc, TEXT("CAMCView::ScAddPageBreakAndNavigate"));
CIdleTaskQueue* pIdleTaskQueue = AMCGetIdleTaskQueue();
sc = ScCheckPointers(pIdleTaskQueue, E_UNEXPECTED);
if(sc)
return sc;
if ( fNavigate && szURL == NULL )
return sc = E_INVALIDARG;
/*
* create the deferred page break task
*/
CAutoPtr<CDeferredPageBreak> spDeferredPageBreak (new CDeferredPageBreak (m_nAddPageBreakAndNavigateMsg, m_hWnd,
MAKEWPARAM(fAddPageBreak, fNavigate),
szURL));
sc = ScCheckPointers(spDeferredPageBreak, E_OUTOFMEMORY);
if(sc)
return sc;
/*
* put the task in the queue, which will take ownership of it
*/
sc = pIdleTaskQueue->ScPushTask (spDeferredPageBreak, ePriority_Normal);
if (sc)
return sc;
/*
* if we get here, the idle task queue owns the idle task, so
* we can detach it from our smart pointer
*/
spDeferredPageBreak.Detach();
/*
* jiggle the message pump so that it wakes up and checks idle tasks
*/
PostMessage (WM_NULL);
return (S_OK);
}
/***************************************************************************\
*
* METHOD: CAMCView::OnAddPageBreakAndNavigate
*
* PURPOSE: Puts a page break and/or navigates to a new webapge
* This method will be called to perfor 3 kinds of the jobs:
* 1. Add a pagebreak (used when selection changes from the web page to list view)
* 2. Add a pagebreak and navigate
* (a. when selection changes from web page to another web page)
* (b. when selection changes from list view to the webpage
* and it is the first web page in the history)
* 3. Navigate only. ( when navigating from list view to the webpage -
* if pagebreak had to be added when leaving the previos web page)
*
* PARAMETERS:
* LOWORD(wParam) - nonzero if page break needs to be added
* HIWORD(wParam) - nonzero if navigation should take place
* LPARAM lParam - not used
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
LRESULT CAMCView::OnAddPageBreakAndNavigate (WPARAM wParam, LPARAM lParam)
{
DECLARE_SC(sc, TEXT("CAMCView::OnAddPageBreakAndNavigate"));
BOOL bAddPageBreak = (BOOL)LOWORD(wParam);
BOOL bNavigate = (BOOL)HIWORD(wParam);
// check the pointer we will need here
CHistoryList* pHistoryList = GetHistoryList();
sc = ScCheckPointers( pHistoryList, m_pWebViewCtrl, E_UNEXPECTED);
if (sc)
return 0;
if (bAddPageBreak)
{
sc = pHistoryList->ScDoPageBreak();
if (sc)
return 0;
}
if (bNavigate)
{
LPCTSTR szURL = reinterpret_cast<LPCTSTR>(lParam);
sc = ScCheckPointers( szURL );
if (sc)
return 0;
m_pWebViewCtrl->Navigate( szURL, NULL );
}
return 0;
}
//############################################################################
//############################################################################
//
// Implementation of class CViewTemplate
//
//############################################################################
//############################################################################
/***************************************************************************\
*
* METHOD: CViewTemplateList::Persist
*
* PURPOSE: Used when loading XML. Persist enough information to create a view
* The rest of view peristence is dome by CAMCView
*
* PARAMETERS:
* CPersistor& persistor - persistor to load from
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
void CViewTemplateList::Persist(CPersistor& persistor)
{
// the view should be stored instead
ASSERT (persistor.IsLoading());
// delegate to the base class
XMLListCollectionBase::Persist(persistor);
}
/***************************************************************************\
*
* METHOD: CViewTemplateList::OnNewElement
*
* PURPOSE: Called by XMLListCollectionBase to request persisting of new element
* Each new element is created and persisted in this function.
*
* PARAMETERS:
* CPersistor& persistor - persisto from which the element should be loaded
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
void CViewTemplateList::OnNewElement(CPersistor& persistor)
{
CBookmark bm;
int iViewId = -1;
// load information byte for new view
CPersistor persistorView(persistor, CAMCView::_GetXMLType());
persistorView.Persist(bm, XML_NAME_ROOT_NODE);
persistorView.PersistAttribute(XML_ATTR_VIEW_ID, iViewId);
// store information to the list
m_ViewsList.push_back(ViewTempl_Type(iViewId, ViewTemplB_Type(bm, persistorView)));
}
//+-------------------------------------------------------------------
//
// Member: ScUpdateStandardbarMMCButtons
//
// Synopsis: Appropriately enable/disable std-toolbar buttons
// that are owned by MMC (not verb buttons that snapins own) like
// back, forward, export-list, up-one-level, show/hide-scope, help.
//
// Arguments: None.
//
//--------------------------------------------------------------------
SC CAMCView::ScUpdateStandardbarMMCButtons()
{
DECLARE_SC (sc, _T("CAMCView::ScUpdateStandardbarMMCButtons"));
// Get the standard toolbar and change the states.
CStandardToolbar* pStdToolbar = GetStdToolbar();
if (NULL == pStdToolbar)
return (sc = E_UNEXPECTED);
CAMCDoc *pDoc = GetDocument();
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
if (sc)
return sc;
// If view is not customizable then hide the "Show/Hide scope tree" button.
sc = pStdToolbar->ScEnableScopePaneBtn(IsScopePaneAllowed() && pDoc->AllowViewCustomization());
if (sc)
sc.TraceAndClear();
sc = pStdToolbar->ScEnableContextHelpBtn(true);
if (sc)
sc.TraceAndClear();
sc = pStdToolbar->ScEnableExportList(GetListSize() > 0 /*Enable only if LV has items*/);
if (sc)
sc.TraceAndClear();
// Enable/Disable Up-One Level button.
BOOL bEnableUpOneLevel = !m_pTreeCtrl->IsRootItemSel();
sc = pStdToolbar->ScEnableUpOneLevel(bEnableUpOneLevel);
if (sc)
sc.TraceAndClear();
// Now update history related buttons.
sc = ScCheckPointers(m_pHistoryList, E_UNEXPECTED);
if (sc)
return sc;
m_pHistoryList->MaintainWebBar();
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScUpdateMMCMenus
//
// Synopsis: Show or Hide MMC menus depending on if they are allowed
// or not. Should do this only if our view owns the menus
// that is we are the active view. (Action/View/Favs)
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScUpdateMMCMenus ()
{
DECLARE_SC(sc, _T("CAMCView::ScUpdateMMCMenus"));
CMainFrame* pMainFrame = AMCGetMainWnd();
sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
if (sc)
return sc;
if (this != pMainFrame->GetActiveAMCView())
return (sc = S_OK); // we are not active view so it is ok.
// We are active view so tell mainframe to update the menus.
sc = pMainFrame->ScShowMMCMenus(m_ViewData.IsStandardMenusAllowed());
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScCreateToolbarObjects
//
// Synopsis: Create the CAMCViewToolbars that manages all toolbar data
// for this view & CStandardToolbar objects.
//
// Arguments: None.
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScCreateToolbarObjects ()
{
DECLARE_SC(sc, _T("CAMCView::ScCreateToolbarObjects"));
CMainFrame *pMainFrame = AMCGetMainWnd();
sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
if (sc)
return sc;
// Create the toolbars for this view.
CMMCToolBar *pMainToolbar = pMainFrame->GetMainToolbar();
sc = ScCheckPointers(pMainToolbar, E_OUTOFMEMORY);
if (sc)
return sc;
m_spAMCViewToolbars = std::auto_ptr<CAMCViewToolbars>(new CAMCViewToolbars(pMainToolbar, this));
sc = ScCheckPointers(m_spAMCViewToolbars.get(), E_FAIL);
if (sc)
return sc;
m_ViewData.SetAMCViewToolbarsMgr(m_spAMCViewToolbars.get() );
sc = m_spAMCViewToolbars->ScInit();
if (sc)
return sc;
// This CAMCViewToolbars is interested in view activation/de-activation/destruction events.
AddObserver( (CAMCViewObserver&) (*m_spAMCViewToolbars) );
// Main toolbar UI is interested in the active CAMCViewToolbars.
m_spAMCViewToolbars->AddObserver( *static_cast<CAMCViewToolbarsObserver *>(pMainToolbar) );
// MMC application is interested in the toolbar event, since it needs to inform the script
CAMCApp *pCAMCApp = AMCGetApp();
if ( pCAMCApp )
m_spAMCViewToolbars->AddObserver( *static_cast<CAMCViewToolbarsObserver *>(pCAMCApp) );
// Create standard toolbar.
m_spStandardToolbar = std::auto_ptr<CStandardToolbar>(new CStandardToolbar());
sc = ScCheckPointers(m_spStandardToolbar.get(), E_OUTOFMEMORY);
if (sc)
return sc;
m_ViewData.SetStdVerbButtons(m_spStandardToolbar.get());
return (sc);
}
/*+-------------------------------------------------------------------------*
* class CMMCViewFrame
*
*
* PURPOSE: The COM 0bject that exposes the Frame interface off the View object.
*
*+-------------------------------------------------------------------------*/
class CMMCViewFrame :
public CMMCIDispatchImpl<Frame>,
public CTiedComObject<CAMCView>
{
typedef CAMCView CMyTiedObject;
typedef CMMCViewFrame ThisClass;
public:
BEGIN_MMC_COM_MAP(ThisClass)
END_MMC_COM_MAP()
//Frame interface
public:
MMC_METHOD0( Maximize );
MMC_METHOD0( Minimize );
MMC_METHOD0( Restore );
MMC_METHOD1( get_Left, LPINT );
MMC_METHOD1( put_Left, INT );
MMC_METHOD1( get_Right, LPINT );
MMC_METHOD1( put_Right, INT );
MMC_METHOD1( get_Top, LPINT );
MMC_METHOD1( put_Top, INT );
MMC_METHOD1( get_Bottom, LPINT );
MMC_METHOD1( put_Bottom, INT );
};
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetFrame
*
* PURPOSE: Returns a pointer to the COM object that implements the
* Frame interface.
*
* PARAMETERS:
* Frame **ppFrame :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::Scget_Frame(Frame **ppFrame)
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetFrame") );
if(!ppFrame)
{
sc = E_POINTER;
return sc;
}
// init out parameter
*ppFrame = NULL;
// create a CMMCApplicationFrame if not already done so.
sc = CTiedComObjectCreator<CMMCViewFrame>::ScCreateAndConnect(*this, m_spFrame);
if(sc)
return sc;
if(m_spFrame == NULL)
{
sc = E_UNEXPECTED;
return sc;
}
// addref the pointer for the client.
m_spFrame->AddRef();
*ppFrame = m_spFrame;
return sc;
}
/***************************************************************************\
| Frame interface |
\***************************************************************************/
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScMaximize
*
* PURPOSE: Maximizes frame window of the view
*
* PARAMETERS:
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScMaximize ()
{
DECLARE_SC(sc, TEXT("CAMCView::ScMaximize"));
CChildFrame *pFrame = GetParentFrame();
sc = ScCheckPointers(pFrame, E_FAIL);
if (sc)
return sc;
pFrame->ShowWindow(SW_MAXIMIZE);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScMinimize
*
* PURPOSE: Minimizes frame window of the view
*
* PARAMETERS:
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScMinimize ()
{
DECLARE_SC(sc, TEXT("CAMCView::ScMinimize"));
CChildFrame *pFrame = GetParentFrame();
sc = ScCheckPointers(pFrame, E_FAIL);
if (sc)
return sc;
pFrame->ShowWindow(SW_MINIMIZE);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScRestore
*
* PURPOSE: Restores frame window of the view
*
* PARAMETERS:
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScRestore ()
{
DECLARE_SC(sc, TEXT("CAMCView::ScRestore"));
CChildFrame *pFrame = GetParentFrame();
sc = ScCheckPointers(pFrame, E_FAIL);
if (sc)
return sc;
pFrame->ShowWindow(SW_RESTORE);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetFrameCoord
*
* PURPOSE: Helper method. Returns specified coordinate of the parent frame
*
* PARAMETERS:
* LPINT pCoord - storage for return value
* coord_t eCoord - which coordinate to return (LEFT, TOP, etc)
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScGetFrameCoord ( LPINT pCoord, coord_t eCoord )
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetFrameCoord"));
// get & check frame ptr
CChildFrame *pFrame = GetParentFrame();
sc = ScCheckPointers(pFrame, E_FAIL);
if (sc)
return sc;
CWnd *pParent = pFrame->GetParent();
sc = ScCheckPointers (pParent, E_FAIL);
if (sc)
return (sc);
// get coordinates of frame window relative to its parent
CWindowRect rcFrame (pFrame);
pParent->ScreenToClient(rcFrame);
// assign to result
sc = ScGetRectCoord (rcFrame, pCoord, eCoord);
if (sc)
return (sc);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScSetFrameCoord
*
* PURPOSE: Helper method. Sets specified coordinate of the parent frame
*
* PARAMETERS:
* INT coord - new value to set
* coord_t eCoord - which coordinate to modify (LEFT, TOP, etc)
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScSetFrameCoord ( INT coord, coord_t eCoord )
{
DECLARE_SC(sc, TEXT("CAMCView::ScSetFrameCoord"));
CChildFrame *pFrame = GetParentFrame();
sc = ScCheckPointers(pFrame, E_FAIL);
if (sc)
return sc;
CWnd *pParent = pFrame->GetParent();
sc = ScCheckPointers (pParent, E_FAIL);
if (sc)
return (sc);
// get coordinates of frame window relative to its parent
CWindowRect rcFrame (pFrame);
pParent->ScreenToClient(rcFrame);
// change the rectangle's specified coordinate
sc = ScSetRectCoord (rcFrame, coord, eCoord);
if (sc)
return (sc);
// move the window
pFrame->MoveWindow (rcFrame);
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScGetRectCoord
*
* PURPOSE: Helper method. Returns specified coordinate of the given rectangle
*
* PARAMETERS:
* const RECT& rect - rectangle to query
* LPINT pCoord - storage for return value
* coord_t eCoord - which coordinate to return (LEFT, TOP, etc)
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScGetRectCoord ( const RECT& rect, LPINT pCoord, coord_t eCoord )
{
DECLARE_SC(sc, TEXT("CAMCView::ScGetRectCoord"));
// check parameters
sc = ScCheckPointers(pCoord);
if (sc)
return sc;
// assign to result
switch (eCoord)
{
case LEFT: *pCoord = rect.left; break;
case RIGHT: *pCoord = rect.right; break;
case TOP: *pCoord = rect.top; break;
case BOTTOM: *pCoord = rect.bottom; break;
default:
*pCoord = 0;
sc = E_INVALIDARG;
break;
}
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScSetRectCoord
*
* PURPOSE: Helper method. Sets specified coordinate of the given rectangle
*
* PARAMETERS:
* RECT& rect - rectangle to modify
* INT coord - new value to set
* coord_t eCoord - which coordinate to modify (LEFT, TOP, etc)
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::ScSetRectCoord ( RECT& rect, INT coord, coord_t eCoord )
{
DECLARE_SC(sc, TEXT("CAMCView::ScSetRectCoord"));
// assign coordinate
switch (eCoord)
{
case LEFT: rect.left = coord; break;
case RIGHT: rect.right = coord; break;
case TOP: rect.top = coord; break;
case BOTTOM: rect.bottom = coord; break;
default: sc = E_INVALIDARG; break;
}
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_Left
*
* PURPOSE: Implements Frame.Left property's Get method for view
*
* PARAMETERS:
* LPINT pCoord - storage for return value
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scget_Left ( LPINT pCoord )
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_Left"));
sc = ScGetFrameCoord( pCoord, LEFT );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scput_Left
*
* PURPOSE: Implements Frame.Left property's Put method for view
*
* PARAMETERS:
* INT coord - value to set
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scput_Left ( INT coord )
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_Left"));
sc = ScSetFrameCoord( coord, LEFT );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_Right
*
* PURPOSE: Implements Frame.Right property's Get method for view
*
* PARAMETERS:
* LPINT pCoord - storage for return value
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scget_Right ( LPINT pCoord)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_Right"));
sc = ScGetFrameCoord( pCoord, RIGHT );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scput_Right
*
* PURPOSE: Implements Frame.Right property's Put method for view
*
* PARAMETERS:
* INT coord - value to set
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scput_Right ( INT coord )
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_Right"));
sc = ScSetFrameCoord( coord, RIGHT );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_Top
*
* PURPOSE: Implements Frame.Top property's Get method for view
*
* PARAMETERS:
* LPINT pCoord - storage for return value
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scget_Top ( LPINT pCoord)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_Top"));
sc = ScGetFrameCoord( pCoord, TOP );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scput_Top
*
* PURPOSE: Implements Frame.Top property's Put method for view
*
* PARAMETERS:
* INT coord - value to set
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scput_Top ( INT coord )
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_Top"));
sc = ScSetFrameCoord( coord, TOP );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scget_Bottom
*
* PURPOSE: Implements Frame.Bottom property's Get method for view
*
* PARAMETERS:
* LPINT pCoord - storage for return value
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scget_Bottom ( LPINT pCoord)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_Bottom"));
sc = ScGetFrameCoord( pCoord, BOTTOM );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::Scput_Bottom
*
* PURPOSE: Implements Frame.Bottom property's Put method for view
*
* PARAMETERS:
* INT coord - value to set
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC CAMCView::Scput_Bottom ( INT coord )
{
DECLARE_SC(sc, TEXT("CAMCView::Scput_Bottom"));
sc = ScSetFrameCoord( coord, BOTTOM );
if (sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScSetViewExtensionFrame
*
* PURPOSE:
*
* PARAMETERS:
* INT top :
* INT left :
* INT bottom :
* INT right :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScSetViewExtensionFrame(bool bShowListView, INT top, INT left, INT bottom, INT right)
{
DECLARE_SC(sc, TEXT("CAMCView::ScSetViewExtensionFrame"))
/*
* this method is only available while a view extension is active
*/
if (!m_fViewExtended)
return sc; // return silently. NOTE: This method will be removed shortly, as will the view extension hosted frame object,
// once mmc moves the mmcview behavior into the web host's element factory.
/*
* figure out the maximum bounding rectangle for the hosted view,
* mapped to view extension-relative coordinates
*/
CRect rectBound;
CalcMaxHostedFrameRect (rectBound);
#ifdef DBG
CString strDebugMsg;
strDebugMsg.Format (_T("CAMCView::ScSetViewExtFrameCoord bound=(l=%d,t=%d,r=%d,b=%d), new = (l=%d,t=%d,r=%d,b=%d)"),
rectBound.left, rectBound.top, rectBound.right, rectBound.bottom,
left, top, right, bottom
);
#endif
/*
* make sure the requested coordinate is withing the permitted area
*/
if (left < rectBound.left)
left = rectBound.left;
if (right > rectBound.right)
right = rectBound.right;
if (top < rectBound.top)
top = rectBound.top;
if (bottom > rectBound.bottom)
bottom = rectBound.bottom;
/*
* if we get here, the view extension-relative coordinate supplied
* is within the acceptable range, now we need to convert it to
* CAMCView-relative coordinates
*/
CPoint pointTopLeft(left, top);
CPoint pointBottomRight(right, bottom);
if ( GetExStyle() & WS_EX_LAYOUTRTL )
{
// IE does not change left/right order on the RTL locales
// thus we need to mirror it's coordinates
// see windows bug #195094 ntbugs9 11/30/00
pointTopLeft.x = rectBound.left + (rectBound.right - right);
pointBottomRight.x = rectBound.left + (rectBound.right - left);
}
MapHostedFramePtToViewPt (pointTopLeft);
MapHostedFramePtToViewPt (pointBottomRight);
/*
* set the coordinates
*/
CRect rectViewExtHostedFrame;
rectViewExtHostedFrame.left = pointTopLeft.x;
rectViewExtHostedFrame.right = pointBottomRight.x;
rectViewExtHostedFrame.top = pointTopLeft.y;
rectViewExtHostedFrame.bottom = pointBottomRight.y;
// move the window to the correct location
CWnd* pwndResult = GetPaneView(ePane_Results);
sc = ScCheckPointers(pwndResult);
if(sc)
return sc;
if (bShowListView)
pwndResult->ShowWindow(SW_SHOW);
::MoveWindow(*pwndResult, rectViewExtHostedFrame.left, rectViewExtHostedFrame.top,
rectViewExtHostedFrame.right - rectViewExtHostedFrame.left,
rectViewExtHostedFrame.bottom - rectViewExtHostedFrame.top,
TRUE /*bRepaint*/);
return (sc);
}
/*+-------------------------------------------------------------------------*
* CAMCView::CalcMaxHostedFrameRect
*
* Returns the maximum rectangle that can be occupied by a view extension's
* hosted frame, normalized around (0,0).
*--------------------------------------------------------------------------*/
void CAMCView::CalcMaxHostedFrameRect (CRect& rect)
{
/*
* start with the result frame rectangle and inset it a little so
* we'll see the client edge provided by the view extension's web
* host view
*/
rect = m_rectResultFrame;
rect.DeflateRect (m_sizEdge);
/*
* now normalize around (0,0)
*/
rect.OffsetRect (-rect.TopLeft());
}
/*+-------------------------------------------------------------------------*
* CAMCView::MapViewPtToHostedFramePt
*
*
*--------------------------------------------------------------------------*/
void CAMCView::MapViewPtToHostedFramePt (CPoint& pt)
{
PointMapperWorker (pt, true);
}
/*+-------------------------------------------------------------------------*
* CAMCView::MapHostedFramePtToViewPt
*
*
*--------------------------------------------------------------------------*/
void CAMCView::MapHostedFramePtToViewPt (CPoint& pt)
{
PointMapperWorker (pt, false);
}
/*+-------------------------------------------------------------------------*
* CAMCView::MapHostedFramePtToViewPt
*
*
*--------------------------------------------------------------------------*/
void CAMCView::PointMapperWorker (CPoint& pt, bool fViewToHostedFrame)
{
int nMultiplier = (fViewToHostedFrame) ? -1 : 1;
/*
* adjust to the origin of the result frame rectangle and for the
* web host view's client edge
*/
pt.Offset (nMultiplier * (m_rectResultFrame.left + m_sizEdge.cx),
nMultiplier * (m_rectResultFrame.top + m_sizEdge.cy));
}
/***************************************************************************\
*
* METHOD: CXMLWindowPlacement::Persist
*
* PURPOSE: Persists window placement settings
*
* PARAMETERS:
* CPersistor &persistor
*
* RETURNS:
* void
*
\***************************************************************************/
void CXMLWindowPlacement::Persist(CPersistor &persistor)
{
// create wrapper to persist flag values as strings
CXMLBitFlags wpFlagsPersistor(m_rData.flags, mappedWPFlags, countof(mappedWPFlags));
// persist the wrapper
persistor.PersistAttribute( XML_ATTR_WIN_PLACEMENT_FLAGS, wpFlagsPersistor );
// persist show command as literal
// create wrapper to persist enumeration values as strings
CXMLEnumeration showCmdPersistor(m_rData.showCmd, mappedSWCommands, countof(mappedSWCommands));
// persist the wrapper
persistor.PersistAttribute( XML_ATTR_SHOW_COMMAND, showCmdPersistor );
persistor.Persist( XMLPoint( XML_NAME_MIN_POSITION, m_rData.ptMinPosition ) );
persistor.Persist( XMLPoint( XML_NAME_MAX_POSITION, m_rData.ptMaxPosition ) );
persistor.Persist( XMLRect( XML_NAME_NORMAL_POSITION, m_rData.rcNormalPosition ) );
}
/***************************************************************************\
*
* METHOD: CAMCView::Scget_Document
*
* PURPOSE: implements View.Document property in object model
*
* PARAMETERS:
* PPDOCUMENT ppDocument [out] document to which the view belongs
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::Scget_Document( PPDOCUMENT ppDocument )
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_Document"));
// parameter check
sc = ScCheckPointers(ppDocument);
if (sc)
return sc;
// get the document
CAMCDoc* pDoc = GetDocument();
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
if (sc)
return sc;
// construct com object
sc = pDoc->ScGetMMCDocument(ppDocument);
if (sc)
return sc;
return (sc);
}
/*******************************************************\
| helper function to avoid too many stack allocations
\*******************************************************/
static tstring W2T_ForLoop(const std::wstring& str)
{
#if defined(_UNICODE)
return str;
#else
USES_CONVERSION;
return W2CA(str.c_str());
#endif
}
/***************************************************************************\
*
* METHOD: CAMCView::ScAddFolderTabs
*
* PURPOSE: Collects view extensions and taskpads and displays them as tabs
*
* PARAMETERS:
* HNODE hNode - selected scope node
* const CLSID &guidTabToSelect - tab to select
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::ScAddFolderTabs( HNODE hNode, const CLSID& guidTabToSelect )
{
DECLARE_SC(sc, TEXT("CAMCView::ScAddFolderTabs"));
sc = ScCheckPointers(m_pResultFolderTabView, E_UNEXPECTED);
if (sc)
return sc;
// cleanup urls
m_ViewExtensionURLs.clear();
// cleanup view tabs before we do anything else
m_pResultFolderTabView->DeleteAllItems();
// get the callback
INodeCallback* pNodeCallBack = GetNodeCallback();
sc = ScCheckPointers(pNodeCallBack, m_pResultFolderTabView, E_UNEXPECTED);
if (sc)
return sc;
// collect view extensions
CViewExtCollection vecExtensions;
CViewExtInsertIterator itExtensions(vecExtensions, vecExtensions.begin());
sc = pNodeCallBack->GetNodeViewExtensions(hNode, itExtensions);
if (sc)
{
sc.TraceAndClear();
vecExtensions.clear();
// continue anyway
}
// check if there is something to show
if(vecExtensions.size() == 0) // no tabs to show.
{
m_pResultFolderTabView->SetVisible(false);
}
else
{
bool bAddDefaultTab = true;
// add extensions
CViewExtCollection::iterator iterVE;
for(iterVE = vecExtensions.begin(); iterVE != vecExtensions.end(); ++iterVE)
{
tstring strName( W2T_ForLoop(iterVE->strName) );
m_pResultFolderTabView->AddItem(strName.c_str(), iterVE->viewID);
m_ViewExtensionURLs[iterVE->viewID] = W2T_ForLoop(iterVE->strURL);
// do not add the "normal" tab if we have a valid replacement for it
if (iterVE->bReplacesDefaultView)
bAddDefaultTab = false;
}
// add the default item.
if (bAddDefaultTab)
{
CStr strNormal;
strNormal.LoadString(GetStringModule(), IDS_NORMAL);
m_pResultFolderTabView->AddItem(strNormal, GUID_NULL);
}
// select required item and show tabs
int iIndex = m_pResultFolderTabView->SelectItemByClsid(guidTabToSelect);
if (iIndex < 0)
TraceError(_T("CAMCView::ScAddFolderTabs - failed to select requested folder"), SC(E_FAIL));
// no need for cotrol if we only have one tab
bool bMoreThanOneTab = (m_pResultFolderTabView->GetItemCount() > 1);
m_pResultFolderTabView->SetVisible(bMoreThanOneTab);
}
// lookup view extension URL
CViewExtensionURLs::iterator itVE = m_ViewExtensionURLs.find(guidTabToSelect);
LPCTSTR url = (itVE != m_ViewExtensionURLs.end()) ? itVE->second.c_str() : NULL;
// apply URL
sc = ScApplyViewExtension(url);
if (sc)
sc.TraceAndClear();
RecalcLayout();
return sc;
}
/***************************************************************************\
*
* METHOD: CAMCView::Scget_ControlObject
*
* PURPOSE: returns IDispatch of embeded OCX control
* implements View.ControlObject property
*
* PARAMETERS:
* PPDISPATCH ppControl [out] control's interface
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CAMCView::Scget_ControlObject( PPDISPATCH ppControl)
{
DECLARE_SC(sc, TEXT("CAMCView::Scget_ControlObject"));
// parameter check
sc = ScCheckPointers(ppControl);
if (sc)
return sc;
// init out param
*ppControl = NULL;
// have a OCX view?
if ( (! HasOCX()) || (m_pOCXHostView == NULL))
return sc.FromMMC( MMC_E_NO_OCX_IN_VIEW );
// get the control's interface
CComQIPtr<IDispatch> spDispatch = m_pOCXHostView->GetIUnknown();
if (spDispatch == NULL)
return sc = E_NOINTERFACE;
// return the pointer
*ppControl = spDispatch.Detach();
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScTreeViewSelectionActivate
//
// Synopsis: Only the list(/Web/OCX) or the tree can be "active" from the point
// of view of selected items and MMCN_SELECT. This is not
// the same as the MFC concept of "active view". There are a couple
// of views that cannot be active in this sense, such as the taskpad
// and tab views.
// When the active view (according to this definition) changes, this
// function is called. Thus, ScTreeViewSelectionActivate and
// ScListViewSelectionActivate/ScSpecialResultpaneSelectionActivate
// are always called in pairs when the activation changes, one to handle
// deactivation, and one to handle activation.
//
// Consider the following scenario
// 1) The tree view has (MFC/windows style) focus.
// 2) The user clicks on the taskpad view
// Result - selection activation does not change from the tree. All verbs
// still correspond to the selected tree item.
// 3) The user clicks on the folder view
// Result - once again, selection activation does not chang
// 4) The user clicks on one of the result views eg the list
// Result - ScTreeViewSelectionActivate(false) and ScListViewSelectionActivate(true)
// Thus verbs and the toolbar now correspond to the selected list item(s).
// 5) The user clicks on the taskpad view.
// Result - as in step 2, nothing happens
// 6) The user clicks on the result view
// Result - because the active view has not changed, nothing happens.
//
// Arguments: [bActivate] - [in]
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScTreeViewSelectionActivate (bool bActivate)
{
DECLARE_SC(sc, _T("CAMCView::ScTreeViewSelectionActivate"));
sc = ScCheckPointers(m_pTreeCtrl, E_UNEXPECTED);
if (sc)
return sc;
// 1. Setup the SELECTINFO
SELECTIONINFO selInfo;
ZeroMemory(&selInfo, sizeof(selInfo));
selInfo.m_bScope = TRUE;
selInfo.m_pView = NULL;
selInfo.m_bDueToFocusChange = TRUE;
if (HasOCX())
{
selInfo.m_bResultPaneIsOCX = true;
selInfo.m_lCookie = LVDATA_CUSTOMOCX;
}
else if (HasWebBrowser())
{
selInfo.m_bResultPaneIsWeb = TRUE;
selInfo.m_lCookie = LVDATA_CUSTOMWEB;
}
HTREEITEM htiSelected = m_pTreeCtrl->GetSelectedItem();
HNODE hSelectedNode = (htiSelected != NULL) ? m_pTreeCtrl->GetItemNode (htiSelected) : NULL;
// insure that this is the active view when we have the focus
ASSERT ( ( (bActivate) && (GetParentFrame()->GetActiveView () == m_pTreeCtrl) ) ||
( (!bActivate) && (GetParentFrame()->GetActiveView () != m_pTreeCtrl) ) );
if (hSelectedNode != NULL)
{
// Send select notification.
sc = ScNotifySelect ( GetNodeCallback(), hSelectedNode,
false /*fMultiSelect*/, bActivate, &selInfo);
if (sc)
return sc;
}
else if ( (htiSelected == NULL) && (bActivate) )
{
m_pTreeCtrl->SelectItem (m_pTreeCtrl->GetRootItem());
}
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScOnTreeViewActivated
//
// Synopsis: Observer implementation for tree-view activation.
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScOnTreeViewActivated ()
{
DECLARE_SC(sc, _T("CAMCView::ScOnTreeViewActivated"));
if (m_eCurrentActivePane == eActivePaneScope) // Scope pane is already active so return.
return sc;
#ifdef DBG
Trace (tagViewActivation, _T("Deactivate %s in result pane Activate Scope pane\n"),
HasListOrListPad() ? _T("ListView") : (HasOCX() ? _T("OCX") : _T("WebBrowser")));
#endif
if (m_eCurrentActivePane == eActivePaneResult)
{
// Send deactivate to result.
if (HasListOrListPad())
sc = ScListViewSelectionActivate (false);
else if (HasOCX() || HasWebBrowser())
sc = ScSpecialResultpaneSelectionActivate(false);
else
return (sc = E_UNEXPECTED);
if (sc)
sc.TraceAndClear();
}
// Send select to scope.
m_eCurrentActivePane = eActivePaneScope;
sc = ScTreeViewSelectionActivate(true);
if (sc)
return sc;
return (sc);
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScOnListViewActivated
//
// Synopsis: Observer implementation for list-view activation.
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScOnListViewActivated ()
{
DECLARE_SC(sc, _T("CAMCView::ScOnListViewActivated"));
if (m_eCurrentActivePane == eActivePaneResult) // Result pane is already active so return.
return sc;
#ifdef DBG
Trace (tagViewActivation, _T("Deactivate Scope pane Activate ListView in Result pane\n"));
#endif
if (m_eCurrentActivePane == eActivePaneScope)
{
// Send deactivate to scope.
sc = ScTreeViewSelectionActivate(false);
if (sc)
sc.TraceAndClear();
}
// Send activate to list.
m_eCurrentActivePane = eActivePaneResult;
ASSERT(HasListOrListPad());
sc = ScListViewSelectionActivate (true);
if (sc)
sc.TraceAndClear();
return (sc);
}
/*+-------------------------------------------------------------------------*
*
* CAMCView::ScOnListViewItemUpdated
*
* PURPOSE: called when an item is updated. This method fires an event to all COM observers.
*
* PARAMETERS:
* int nIndex :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CAMCView::ScOnListViewItemUpdated (int nIndex)
{
DECLARE_SC(sc, _T("CAMCView::ScOnListViewItemUpdated"));
// fire event
sc = ScFireEvent(CAMCViewObserver::ScOnListViewItemUpdated, this, nIndex);
if (sc)
return sc;
return sc;
}
//+-------------------------------------------------------------------
//
// Member: CAMCView::ScOnOCXHostActivated
//
// Synopsis: Observer implementation for ocx or web view activation.
//
// Arguments:
//
// Returns: SC
//
//--------------------------------------------------------------------
SC CAMCView::ScOnOCXHostActivated ()
{
DECLARE_SC(sc, _T("CAMCView::ScOnOCXHostActivated"));
if (m_eCurrentActivePane == eActivePaneResult) // Result pane is already active so return.
return sc;
#ifdef DBG
Trace (tagViewActivation, _T("Deactivate Scope pane Activate %s in Result pane\n"),
HasOCX() ? _T("OCX") : _T("WebBrowser"));
#endif
if (m_eCurrentActivePane == eActivePaneScope)
{
// Send deactivate to scope.
sc = ScTreeViewSelectionActivate(false);
if (sc)
sc.TraceAndClear();
}
// Send select to ocx or web view.
m_eCurrentActivePane = eActivePaneResult;
ASSERT(HasOCX() || HasWebBrowser());
sc = ScSpecialResultpaneSelectionActivate(true);
if (sc)
sc.TraceAndClear();
return (sc);
}