gecko-dev/cmd/winfe/navcntr.cpp

1345 строки
36 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "stdafx.h"
#include "navfram.h"
#include "feimage.h"
#include "net.h"
#include "cxsave.h"
#include "cxicon.h"
#include "fegui.h"
#include "rdfliner.h"
#include "mmsystem.h"
#include "winproto.h"
#include "xp_ncent.h"
#include "pain.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef _AFXDLL
#undef new
#endif
#ifndef _AFXDLL
#define new DEBUG_NEW
#endif
#include "dropmenu.h"
//////////////////////////
// RDF Event Handlers
// The Main Event Handler for the NavCenter. Handles events on the selector bar AND within the tree
// views.
void notifyProcedure (HT_Notification ns, HT_Resource n, HT_Event whatHappened)
{
CSelector* theSelector = (CSelector*)ns->data;
if (theSelector == NULL)
return;
HT_View theView = HT_GetView(n);
// The pane has to handle some events. These will go here.
if (whatHappened == HT_EVENT_VIEW_SELECTED)
{
CView* pView = theSelector->GetCurrentView();
CSelectorButton* pButton = theSelector->GetCurrentButton();
// If the new selected view is NULL, then we need to make sure our pane is closed.
if (theView == NULL && pView != NULL)
{
// We're open. Close the pane.
((CNSNavFrame*)theSelector->GetParentFrame())->CollapseWindow();
}
else if (theView != NULL)
{
// We have a view. Select it.
CSelectorButton* pButton = (CSelectorButton*)HT_GetViewFEData(theView);
theSelector->SetCurrentView(pButton);
if (pView == NULL)
{
// Need to open the pane.
((CNSNavFrame*)theSelector->GetParentFrame())->ExpandWindow();
}
}
return;
}
if (theView == NULL)
return;
if (whatHappened == HT_EVENT_VIEW_ADDED)
{
theSelector->ConstructView(theView);
theSelector->RearrangeIcons();
CSelectorButton* pButton = (CSelectorButton*)HT_GetViewFEData(theView);
}
else if (whatHappened == HT_EVENT_VIEW_DELETED)
{
// Delete the content view
CSelectorButton* pButton = (CSelectorButton*)HT_GetViewFEData(theView);
if (pButton)
{
pButton->GetView()->DestroyWindow();
// Delete the button
delete pButton;
// Remove our FE data
HT_SetViewFEData(theView, NULL);
}
}
else if (whatHappened == HT_EVENT_NODE_VPROP_CHANGED && HT_TopNode(theView) == n)
{
// Top level node changed its name/icon. Need to change the button text, window title bar, and
// embedded nav menu bar. Also need to update the current tree view and the column headers. (Whew!)
CSelectorButton* pButton = (CSelectorButton*)HT_GetViewFEData(theView);
if (pButton && pButton->m_hWnd)
{
// Invalidate the button.
pButton->Invalidate();
// Invalidate the title bar.
CFrameWnd* pFrame = pButton->GetParentFrame();
if (pFrame->IsKindOf(RUNTIME_CLASS(CNSNavFrame)))
{
CNSNavFrame* pNavFrame = (CNSNavFrame*)pFrame;
if (pNavFrame)
{
// Invalidate the title bar.
CNavMenuBar* pBar = pNavFrame->GetNavMenuBar();
if (pBar)
pBar->Invalidate();
// Invalidate the tree view.
CRDFContentView* theOutlinerView = (CRDFContentView*)pButton->GetTreeView();
if (theOutlinerView)
{
CRDFOutlinerParent* pParent = (CRDFOutlinerParent*)(theOutlinerView->GetOutlinerParent());
if (pParent)
{
pParent->Invalidate();
COutliner* pOutliner = pParent->GetOutliner();
if (pOutliner)
pOutliner->Invalidate();
}
}
}
}
}
}
else if (whatHappened == HT_EVENT_NODE_EDIT && HT_TopNode(theView) == n)
{
// Edit being performed on a selector bar item. (STILL TO DO)
}
else if (whatHappened == HT_EVENT_VIEW_WORKSPACE_REFRESH)
theSelector->RearrangeIcons(); // Redraw the selector.
// If the pane doesn't handle the event, then a view does.
else
{
// View needs to exist in order for us to send this event to it.
CSelectorButton* pButton = (CSelectorButton*)HT_GetViewFEData(theView);
if (pButton)
{
CRDFContentView* theOutlinerView = (CRDFContentView*)pButton->GetTreeView();
if (theOutlinerView)
{
CRDFOutliner* theOutliner = (CRDFOutliner*)(theOutlinerView->GetOutlinerParent()->GetOutliner());
theOutliner->HandleEvent(ns, n, whatHappened);
}
}
}
}
// The Event Handler for selector popup menus
static void selectorPopupNotifyProcedure (HT_Notification ns, HT_Resource n, HT_Event whatHappened)
{
// We respond only to open/closed events. This procedure is only entered when the user clicks
// and holds on a selector bar button to bring up a popup menu.
CSelectorButton* theButton = (CSelectorButton*)ns->data;
if (n != NULL)
{
HT_View theView = HT_GetView(n);
if (theView != NULL && (whatHappened == HT_EVENT_NODE_OPENCLOSE_CHANGED))
{
PRBool openState;
HT_GetOpenState(n, &openState);
if (openState)
{
theButton->FillInMenu(n);
}
}
}
}
// SelectorButton
CSelectorButton::~CSelectorButton()
{
if (m_Pane)
HT_DeletePane(m_Pane);
m_Node = NULL;
}
int CSelectorButton::Create(CWnd *pParent, int nToolbarStyle, CSize noviceButtonSize,
CSize advancedButtonSize,
LPCTSTR pButtonText, LPCTSTR pToolTipText,
LPCTSTR pStatusText,
CSize bitmapSize, int nMaxTextChars, int nMinTextChars,
HT_Resource pNode,
DWORD dwButtonStyle, CView* view, CPaneCX* pane)
{
pView = view;
m_pPane = pane;
// Construct the notification struct used by HT
HT_Notification ns = new HT_NotificationStruct;
ns->notifyProc = selectorPopupNotifyProcedure;
ns->data = this;
// Construct the pane and give it our notification struct
m_Pane = HT_PaneFromResource(HT_GetRDFResource(pNode), ns, (PRBool)TRUE);
HT_SetPaneFEData(m_Pane, this);
HT_Resource pEntry = NULL;
HT_View theView = HT_GetSelectedView(m_Pane);
BOOKMARKITEM bookmark; // For now, create with the pictures style. No text ever.
return CRDFToolbarButton::Create(pParent, TB_PICTURES, noviceButtonSize, advancedButtonSize,
pButtonText, pToolTipText, pStatusText, bitmapSize, nMaxTextChars, nMinTextChars,
bookmark, HT_TopNode(theView), dwButtonStyle);
}
void CSelectorButton::OnAction()
{
if (m_pDropMenu == NULL || !m_pDropMenu->IsOpen())
{
HT_Pane pane = HT_GetPane(m_HTView);
if (m_pSelector->GetCurrentButton() == this)
{
// View is already selected. We are now closing the pane.
HT_SetSelectedView(pane, NULL);
}
else HT_SetSelectedView(pane, m_HTView);
}
}
CSize CSelectorButton::GetButtonSizeFromChars(CString s, int c)
{
if (m_nToolbarStyle == TB_PICTURES)
return GetBitmapOnlySize();
else if(m_nToolbarStyle == TB_TEXT)
return(GetTextOnlySize(s, c));
else
return(GetBitmapOnTopSize(s, c));
}
void CSelectorButton::DrawPicturesMode(HDC hDC, CRect rect)
{
DrawButtonBitmap(hDC, rect);
}
void CSelectorButton::DrawPicturesAndTextMode(HDC hDC, CRect rect)
{
//DrawBitmapOnTop(hDC, rect);
DrawButtonBitmap(hDC, rect);
}
void CSelectorButton::GetPicturesAndTextModeTextRect(CRect &rect)
{
//GetBitmapOnTopTextRect(rect);
GetPicturesModeTextRect(rect);
}
void CSelectorButton::GetPicturesModeTextRect(CRect &rect)
{
//GetBitmapOnTopTextRect(rect);
CToolbarButton::GetPicturesModeTextRect(rect);
}
void CSelectorButton::DisplayMenuOnDrag()
{
CPoint point = RequestMenuPlacement();
if(m_pDropMenu == NULL || !m_pDropMenu->IsOpen())
{
int nCount;
if(m_pDropMenu != NULL)
{
nCount = m_pDropMenu->GetMenuItemCount();
// clean out the menu before adding to it
for(int i = nCount - 1; i >= 0; i--)
{
m_pDropMenu->DeleteMenu(i, MF_BYPOSITION);
}
m_pDropMenu->DestroyDropMenu();
delete m_pDropMenu;
}
m_pDropMenu = new CDropMenu;
SendMessage(NSDRAGMENUOPEN, (WPARAM)GetButtonCommand(), (LPARAM)m_pDropMenu);
nCount = m_pDropMenu->GetMenuItemCount();
if(nCount > 0)
{
CDropMenuDropTarget *dropTarget = new CDropMenuDropTarget(m_pDropMenu);
m_pDropMenu->TrackDropMenu(this, point.x, point.y, TRUE, dropTarget, TRUE);
}
else
{
CDropMenu* theLastMenu = CDropMenu::GetLastDropMenu();
if(theLastMenu !=NULL)
{
//we only want one drop menu open at a time, so close the last one if one is
//still open.
theLastMenu->Deactivate();
CDropMenu::SetLastDropMenu(NULL);
}
}
}
}
BOOL CSelectorButton::CreateRightMouseMenu()
{
// Selector buttons should be selected if the tree is visible.
if (m_pSelector->IsTreeVisible())
{
// Actually switch to this view.
if (!m_bDepressed)
{
// Depress.
OnAction();
}
}
// Build the actual menu.
m_MenuCommandMap.Clear();
HT_Cursor theCursor = HT_NewContextualMenuCursor(m_HTView, PR_TRUE, PR_FALSE);
if (theCursor != NULL)
{
// We have a cursor. Attempt to iterate
HT_MenuCmd theCommand;
while (HT_NextContextMenuItem(theCursor, &theCommand))
{
char* menuName = HT_GetMenuCmdName(theCommand);
if (theCommand == HT_CMD_SEPARATOR)
m_menu.AppendMenu(MF_SEPARATOR);
else
{
// Add the command to our command map
CRDFMenuCommand* rdfCommand = new CRDFMenuCommand(menuName, theCommand);
int index = m_MenuCommandMap.AddCommand(rdfCommand);
m_menu.AppendMenu(MF_ENABLED, index+FIRST_HT_MENU_ID, menuName);
}
}
HT_DeleteCursor(theCursor);
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CNavCenterFrame
//IMPLEMENT_DYNAMIC(CSelector, CScrollView)
IMPLEMENT_DYNAMIC(CSelector, CView)
BEGIN_MESSAGE_MAP(CSelector, CView)
//{{AFX_MSG_MAP(CMainFrame)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code !
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_MOUSEMOVE()
ON_WM_ERASEBKGND()
ON_WM_PARENTNOTIFY()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_RBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_MESSAGE(NSBUTTONDRAGGING, OnButtonDrag)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CSelector::CSelector()
{
m_pCurView = NULL;
m_xpos = ICONXPOS;
m_ypos = ICONYPOS;
m_pDropTarget = NULL;
m_Pane = NULL;
m_Notification = NULL;
m_scrollPos = 0;
m_pCurButton = NULL;
m_boundingBox.SetRectEmpty();
m_hScrollBmp = ::LoadBitmap( AfxGetResourceHandle(),
MAKEINTRESOURCE( IDB_VFLIPPY ));
BITMAP bm;
::GetObject( m_hScrollBmp, sizeof( bm ), &bm );
m_hScrollBmpSize.cx = bm.bmWidth / 4;
m_hScrollBmpSize.cy = bm.bmHeight;
m_scrollUp = new CNavSelScrollButton(m_hScrollBmp, m_hScrollBmpSize.cx, 0, m_hScrollBmpSize.cy);
m_scrollDown = new CNavSelScrollButton(m_hScrollBmp, m_hScrollBmpSize.cx, 2, m_hScrollBmpSize.cy);
m_scrollDirection = NOSCROLL;
m_hPaneSwitchTimer = 0;
}
CSelector::~CSelector()
{
if (m_hScrollBmp)
{
VERIFY( ::DeleteObject( m_hScrollBmp ));
}
if (m_Pane != NULL)
{
int count = HT_GetViewListCount(m_Pane);
for (int i = 0; i < count; i++)
{
HT_View view = HT_GetNthView(m_Pane, i);
if (view && HT_GetViewFEData(view))
{
CSelectorButton* theButton = (CSelectorButton*)HT_GetViewFEData(view);
delete theButton;
HT_SetViewFEData(view, NULL);
}
}
XP_UnregisterNavCenter(m_Pane);
HT_DeletePane(m_Pane);
}
if (m_scrollUp)
delete m_scrollUp;
if (m_scrollDown)
delete m_scrollDown;
delete m_Notification;
if(m_pDropTarget)
{
m_pDropTarget->Revoke();
delete m_pDropTarget;
m_pDropTarget = NULL;
}
}
void CSelector::OnDraw(CDC* pDC)
{
}
int CSelector::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(!m_pDropTarget) {
m_pDropTarget = new CSelectorDropTarget(this);
m_pDropTarget->Register(this);
}
CRect tempRect(0, 0, 1, 1);
m_scrollUp->Create("", BS_OWNERDRAW | BS_PUSHBUTTON , tempRect, this, SCROLLID);
m_scrollDown->Create("", BS_OWNERDRAW | BS_PUSHBUTTON , tempRect, this, SCROLLID+1);
m_scrollUp->SetWindowPos( &wndTopMost, 0, 0, 1, 1, 0);
m_scrollDown->SetWindowPos( &wndTopMost, 0, 0, 1, 1, 0);
#ifdef XP_WIN32
::SetClassLong(GetSafeHwnd(), GCL_HBRBACKGROUND, (COLOR_BTNFACE + 1));
#else
::SetClassWord(GetSafeHwnd(), GCW_HBRBACKGROUND, (COLOR_BTNFACE + 1));
#endif
return 0;
}
void CSelector::SelectNthView(int i)
{
HT_View theView = HT_GetNthView(m_Pane, i);
if (theView && HT_GetViewFEData(theView))
{
CSelectorButton* pButton = (CSelectorButton*)HT_GetViewFEData(theView);
pButton->OnAction();
}
}
BOOL CSelector::IsTreeVisible()
{
return m_pCurView != NULL;
}
void CSelector::SetCurrentView(CSelectorButton* pButton)
{
CView* pView = pButton->GetView();
if (m_pCurButton)
{
m_pCurButton->SetDepressed(FALSE);
}
m_pCurButton = pButton;
m_pCurButton->SetDepressed(TRUE);
if (m_pCurView != pView )
{
if (m_pCurView)
m_pCurView->ShowWindow(SW_HIDE);
m_pCurView = pView;
GetParentFrame()->SetActiveView( m_pCurView);
((CNSNavFrame*)GetParentFrame())->GetNavMenuBar()->UpdateView(m_pCurButton, m_pCurButton->GetHTView());
((CNSNavFrame*)GetParentFrame())->UpdateTitleBar(m_pCurButton->GetHTView());
}
// adjust the window. here.
m_pCurView->ShowWindow(SW_SHOW);
if(m_pCurView->GetParent()->IsKindOf(RUNTIME_CLASS(CContentView)))
{
CContentView* contentView = (CContentView*)m_pCurView->GetParent();
contentView->CalcChildSizes();
}
m_pCurView->SetFocus();
}
void CSelector::UnSelectAll()
{
if (m_pCurButton)
m_pCurButton->SetDepressed(FALSE);
m_pCurButton = 0;
if (m_pCurView)
{
m_pCurView->ShowWindow(SW_HIDE);
m_pCurView = 0;
GetParentFrame()->SetActiveView( m_pCurView);
}
((CNSNavFrame*)GetParentFrame())->GetNavMenuBar()->UpdateView(NULL, NULL);
}
CView* CSelector::GetCurrentView()
{
return m_pCurView;
}
CSelectorButton* CSelector::GetCurrentButton()
{
return m_pCurButton;
}
void CSelector::OnSize( UINT nType, int cx, int cy )
{
if (cy > m_boundingBox.Height() && m_scrollPos > 0)
{ // resize bigger need to scroll down.
ScrollWindowEx( 0, SCROLLSTEP, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
m_scrollPos -= SCROLLSTEP;
}
int32 dockStyle = ((CNSNavFrame*)GetParent())->GetDockStyle();
if (dockStyle == DOCKSTYLE_HORZTOP || dockStyle == DOCKSTYLE_HORZBOTTOM)
{
int left = cx-m_hScrollBmpSize.cx;
m_scrollUp->MoveWindow(0, 0, m_hScrollBmpSize.cx, m_hScrollBmpSize.cy);
m_scrollUp->setBoundingBox(0, 0, m_hScrollBmpSize.cx, m_hScrollBmpSize.cy);
m_scrollDown->MoveWindow(left, 0, m_hScrollBmpSize.cx , m_hScrollBmpSize.cy);
m_scrollDown->setBoundingBox(left, 0, left + m_hScrollBmpSize.cx, m_hScrollBmpSize.cy);
}
else
{
int top = cy - m_hScrollBmpSize.cy;
int left = cx-m_hScrollBmpSize.cx;
m_scrollUp->MoveWindow(left, 0, m_hScrollBmpSize.cx, m_hScrollBmpSize.cy);
m_scrollUp->setBoundingBox(left, 0, left + m_hScrollBmpSize.cx , m_hScrollBmpSize.cy);
m_scrollDown->MoveWindow(left, top, m_hScrollBmpSize.cx , m_hScrollBmpSize.cy);
m_scrollDown->setBoundingBox(left, top, left + m_hScrollBmpSize.cx, top + m_hScrollBmpSize.cy);
}
ShowScrollButton(NULL);
GetClientRect(&m_boundingBox);
RearrangeIcons();
}
void CSelector::ShowScrollButton(CSelectorButton* button)
{
CRect tempRect;
CNSNavFrame* pParent = (CNSNavFrame*)GetParent();
int32 dockstyle = pParent->GetDockStyle();
GetClientRect(&tempRect);
// checked if we need to display the scroll button
if (dockstyle == DOCKSTYLE_FLOATING || dockstyle == DOCKSTYLE_VERTLEFT ||
dockstyle == DOCKSTYLE_VERTRIGHT) {
if ((m_ypos - m_hScrollBmpSize.cy) > (tempRect.Height() - ICONYPOS)) {
m_scrollUp->ShowWindow(SW_SHOW);
m_scrollDown->ShowWindow(SW_SHOW);
m_scrollUp->Invalidate();
m_scrollDown->Invalidate();
}
else {
m_scrollUp->ShowWindow(SW_HIDE);
m_scrollDown->ShowWindow(SW_HIDE);
}
}
else {
if ((m_xpos - m_hScrollBmpSize.cx) > (tempRect.Width() - ICONXPOS)) {
m_scrollUp->ShowWindow(SW_SHOW);
m_scrollDown->ShowWindow(SW_SHOW);
m_scrollUp->Invalidate();
m_scrollDown->Invalidate();
}
else {
m_scrollUp->ShowWindow(SW_HIDE);
m_scrollDown->ShowWindow(SW_HIDE);
}
}
}
void CSelector::AddViewContext(const char* pTitle, CView* pView, CRDFContentView* pTree,
CPaneCX* htmlPane, HT_View theView)
{
CSelectorButton* theNSViewButton = new CSelectorButton(this);
// Button meets the view. View meets the button.
theNSViewButton->SetHTView(theView);
theNSViewButton->SetTreeView(pTree);
HT_SetViewFEData(theView, theNSViewButton);
HT_Resource node = theView ? HT_TopNode(theView) : NULL;
char* pNodeURL = node ? HT_GetNodeURL(node) : "";
theNSViewButton->Create(this, theApp.m_pToolbarStyle, CSize(60,42), CSize(85, 25),
pTitle,
pTitle, pNodeURL,
CSize(23,23), 10, 5,
node,
TB_HAS_DRAGABLE_MENU | TB_HAS_TIMED_MENU, pView, htmlPane);
CRect rect;
rect.left = (long)m_xpos;
rect.top = (long)m_ypos;
CSize buttonSize = theNSViewButton->GetRequiredButtonSize();
rect.right = rect.left + buttonSize.cx;
rect.bottom = rect.top + buttonSize.cy;
CNSNavFrame* pFrame = (CNSNavFrame*)GetParentFrame();
int32 dockStyle = pFrame->GetDockStyle();
if (dockStyle == DOCKSTYLE_HORZTOP || dockStyle == DOCKSTYLE_HORZBOTTOM)
{
m_xpos += BUTTON_WIDTH + 2;
rect.bottom = rect.top + BUTTON_HEIGHT;
}
else
{
m_ypos += buttonSize.cy + 2;
rect.right = rect.left + BUTTON_WIDTH;
}
/*
CString originalText = HT_GetNodeName(theNSViewButton->GetNode());
int currCount = originalText.GetLength();
// Start off at the maximal string
CString strTxt = originalText;
CSize theSize = theNSViewButton->GetButtonSizeFromChars(originalText, currCount);
int horExtent = theSize.cx;
while (horExtent > BUTTON_WIDTH)
{
strTxt = originalText.Left(currCount-3) + "...";
theSize = theNSViewButton->GetButtonSizeFromChars(strTxt, currCount);
horExtent = theSize.cx;
currCount--;
}
theNSViewButton->SetTextWithoutResize(strTxt);
*/
ShowScrollButton(theNSViewButton);
}
void CSelector::PopulatePane()
{
// Construct the notification struct used by HT
HT_Notification ns = new HT_NotificationStruct;
ns->notifyProc = notifyProcedure;
ns->data = this;
m_Notification = ns;
// Construct the pane and give it our notification struct
m_Pane = HT_NewPane(ns);
HT_SetPaneFEData(m_Pane, this);
// Inform our XP layer of the new nav center.
MWContext *pDockedCX = NULL;
CNSNavFrame *pParentFrame = GetParentFrame()->IsKindOf(RUNTIME_CLASS(CNSNavFrame)) ? (CNSNavFrame*)GetParentFrame() : NULL;
// Since the XP layer isn't set up yet, we can't use
// XP_IsNavCenterDocked in order to tell
// if the window is docked. Use instead wether or
// not the frame has a parent.
if(pParentFrame && pParentFrame->GetParent()) {
CFrameGlue *pGlue = CFrameGlue::GetFrameGlue(pParentFrame->GetTopLevelFrame());
if(pGlue && pGlue->GetMainContext()) {
pDockedCX = pGlue->GetMainContext()->GetContext();
}
ASSERT(pDockedCX);
}
XP_RegisterNavCenter(m_Pane, pDockedCX);
// Place any icons that were immediately available. (The remote ones will trickle in later, and we'll
// rearrange the selector bar when we get those VIEW_ADDED events.)
RearrangeIcons();
}
void CSelector::ConstructView(HT_View theView)
{
if (theView == NULL)
return;
CString viewName = HT_GetNodeName(HT_TopNode(theView));
// Construct the RDF view
CWnd *theParent = (CWnd *)(((CNSNavFrame*)GetParentFrame())->GetContentView());
DWORD dwCurrentStyle = WS_CHILD;
// Parent may change depending on view (need more panes).
CRect rClient(0, 0, 100, 100);
CContentView *pAltParent = NULL;
CPaneCX *pCX = NULL;
if(HT_HasHTMLPane(theView))
{
pAltParent = new CContentView();
pAltParent->Create(NULL, "", WS_CHILD, rClient, theParent, NC_IDW_MISCVIEW, NULL);
pCX = wfe_CreateNavCenterHTMLPain(theView, pAltParent->m_hWnd);
// Make all other children visible now (we control visibility by being the parent).
dwCurrentStyle |= WS_VISIBLE;
}
if(pAltParent) {
theParent = (CWnd *)pAltParent;
}
theParent->GetClientRect(&rClient);
// Can't use CSelector's m_Pane, because it might not have been initialized yet. Calls
// HT_GetPane instead.
CRDFOutlinerParent* newParent = new CRDFOutlinerParent(HT_GetPane(theView), theView);
CRDFContentView* newView = new CRDFContentView(newParent);
// Create the windows
newView->Create( NULL, "", dwCurrentStyle, rClient, theParent, NC_IDW_OUTLINER);
// Initialize the columns, etc.
newParent->Initialize();
// Name and icon for the view correspond to the name/icon of the top node in the view.
AddViewContext(viewName, pAltParent ? (CView *)pAltParent : (CView *)newView, newView, pCX, theView);
}
void CSelector::DestroyViews()
{
int viewCount = HT_GetViewListCount(m_Pane);
for (int i = 0; i < viewCount; i++)
{
HT_View v = HT_GetNthView(m_Pane, i);
if (v != NULL)
{
CRDFContentView* theView = (CRDFContentView*)(HT_GetViewFEData(v));
delete theView;
}
}
}
BOOL CSelector::OnEraseBkgnd( CDC* pDC )
{
int i = 0;
return CWnd::OnEraseBkgnd(pDC);
}
void CSelector::ScrollSelector()
{
if (m_scrollDirection == SCROLLUP || m_scrollDirection == SCROLLLEFT) {
if (m_scrollPos > 0) {
if (m_scrollDirection == SCROLLUP)
ScrollWindowEx( 0, SCROLLSTEP, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
else
ScrollWindowEx( SCROLLSTEP, 0, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
m_scrollPos -= SCROLLSTEP;
}
}
else {
RECT rect;
GetClientRect(&rect);
if (m_scrollDirection == SCROLLDOWN) {
if (m_scrollPos + (rect.bottom - rect.top) < m_ypos) {
ScrollWindowEx( 0, -SCROLLSTEP, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
m_scrollPos += SCROLLSTEP;
}
else if (m_scrollPos + (rect.right - rect.left) < m_xpos) {
ScrollWindowEx( -SCROLLSTEP, 0, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
m_scrollPos += SCROLLSTEP;
}
}
}
ShowScrollButton(NULL);
m_scrollUp->AdjustPos();
m_scrollDown->AdjustPos();
}
void CSelector::OnParentNotify( UINT message, LPARAM lParam )
{
if (message == WM_LBUTTONDOWN) {
POINT pt;
pt.x = LOWORD(lParam); // horizontal position of cursor
pt.y = HIWORD(lParam); // vertical position of cursor
CNSNavFrame* pParent = (CNSNavFrame*)GetParent();
int32 dockStyle = pParent->GetDockStyle();
if (m_scrollUp->IsPtInRect(pt)) {
if (dockStyle == DOCKSTYLE_HORZTOP)
m_scrollDirection = SCROLLLEFT;
else
m_scrollDirection = SCROLLUP;
}
else if (m_scrollDown->IsPtInRect(pt)){ // scroll down.
if (dockStyle == DOCKSTYLE_HORZBOTTOM)
m_scrollDirection = SCROLLRIGHT;
else
m_scrollDirection = SCROLLDOWN;
}
ScrollSelector();
}
CWnd::OnParentNotify( message, lParam );
}
void CSelector::RearrangeIcons()
{
if (m_Pane == NULL)
return;
CNSNavFrame* pFrame = (CNSNavFrame*)GetParentFrame();
int32 dockStyle = pFrame->GetDockStyle();
CRect tempRect;
if (dockStyle == DOCKSTYLE_HORZTOP || dockStyle == DOCKSTYLE_HORZBOTTOM)
{
m_xpos = ICONXPOS;
m_ypos = 2;
}
else {
m_xpos = 2;
m_ypos = ICONYPOS;
}
CRect parentRect;
CSelectorButton* theButton = NULL;
GetClientRect(&parentRect);
int count = HT_GetViewListCount(m_Pane);
for (int i = 0; i < count; i++)
{
HT_View view = HT_GetNthView(m_Pane, i);
if (view && HT_GetViewFEData(view))
{
theButton = (CSelectorButton*)HT_GetViewFEData(view);
CSize buttonSize = theButton->GetRequiredButtonSize();
if (dockStyle == DOCKSTYLE_FLOATING || dockStyle == DOCKSTYLE_VERTLEFT ||
dockStyle == DOCKSTYLE_VERTRIGHT)
{ // draw icon from top to bottom
theButton->MoveWindow((int)m_xpos, (int)m_ypos,
BUTTON_WIDTH, buttonSize.cy, TRUE);
m_ypos += buttonSize.cy + 2;
}
else
{ // draw icon from left to right.
theButton->MoveWindow((int)m_xpos, (int)m_ypos,
BUTTON_WIDTH, buttonSize.cy, TRUE);
m_xpos += BUTTON_WIDTH + 2;
}
}
}
}
CSelectorButton* CSelector::GetButtonFromPoint(CPoint point, int& dragFraction)
{
CRect buttonRect;
CNSNavFrame* pFrame = (CNSNavFrame*)GetParentFrame();
int32 dockStyle = pFrame->GetDockStyle();
CSelectorButton* pButton = NULL;
int count = HT_GetViewListCount(m_Pane);
for (int i = 0; i < count; i++)
{
HT_View view = HT_GetNthView(m_Pane, i);
if (view && HT_GetViewFEData(view))
{
pButton = (CSelectorButton*)HT_GetViewFEData(view);
pButton->GetClientRect(&buttonRect);
pButton->MapWindowPoints(this, &buttonRect);
if (buttonRect.PtInRect(point))
{
int hitY = point.y;
if (point.y >= buttonRect.top && point.y <= buttonRect.top + buttonRect.Height()/4.0)
dragFraction = 1;
else if (point.y >= buttonRect.bottom - buttonRect.Height()/4.0)
dragFraction = 3;
else dragFraction = 2;
return pButton;
}
if (dockStyle == DOCKSTYLE_FLOATING || dockStyle == DOCKSTYLE_VERTLEFT ||
dockStyle == DOCKSTYLE_VERTRIGHT)
{
if (point.y <= buttonRect.bottom)
{
dragFraction = 1;
return pButton;
}
}
else
{
if (point.x <= buttonRect.right)
{
dragFraction = 1;
return pButton;
}
}
}
}
dragFraction = 3;
return pButton;
}
void CSelector::OnTimer(UINT nID)
{
CWnd::OnTimer(nID);
if (nID == IDT_PANESWITCH)
{
if (m_hPaneSwitchTimer != 0)
{
KillSwitchTimer();
}
// Do the pane switch
if (m_pCurButton != GetDragButton())
{
// There's actually something that needs to be done.
if (m_pCurButton) // Something is depressed
GetDragButton()->OnAction();
else // Nothing is depressed. Use popup menus instead.
GetDragButton()->DisplayMenuOnDrag();
}
}
}
void CSelector::OnLButtonDown (UINT nFlags, CPoint point )
{
// Called when the user clicks on the menu bar. Start a drag or collapse the view.
if (m_pCurButton)
{
CRDFContentView* pView = m_pCurButton->GetTreeView();
if (pView)
pView->SetFocus();
}
m_PointHit = point;
SetCapture();
}
void CSelector::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CNSNavFrame* navFrameParent = (CNSNavFrame*)GetParentFrame();
if (abs(point.x - m_PointHit.x) > 3 ||
abs(point.y - m_PointHit.y) > 3)
{
ReleaseCapture();
// Start a drag
MapWindowPoints(navFrameParent, &point, 1);
navFrameParent->StartDrag(point);
}
}
}
void CSelector::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
ReleaseCapture();
}
}
void CSelector::OnRButtonDown(UINT nFlags, CPoint point)
{
m_MenuCommandMap.Clear();
HT_Cursor theCursor = HT_NewContextualMenuCursor(NULL, PR_TRUE, PR_TRUE);
CMenu menu;
ClientToScreen(&point);
if (menu.CreatePopupMenu() != 0 && theCursor != NULL)
{
// We have a cursor. Attempt to iterate
HT_MenuCmd theCommand;
while (HT_NextContextMenuItem(theCursor, &theCommand))
{
char* menuName = HT_GetMenuCmdName(theCommand);
if (theCommand == HT_CMD_SEPARATOR)
menu.AppendMenu(MF_SEPARATOR);
else
{
// Add the command to our command map
CRDFMenuCommand* rdfCommand = new CRDFMenuCommand(menuName, theCommand);
int index = m_MenuCommandMap.AddCommand(rdfCommand);
menu.AppendMenu(MF_ENABLED, index+FIRST_HT_MENU_ID, menuName);
}
}
HT_DeleteCursor(theCursor);
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this, NULL);
menu.DestroyMenu();
}
}
BOOL CSelector::OnCommand( WPARAM wParam, LPARAM lParam )
{
if (wParam >= FIRST_HT_MENU_ID && wParam <= LAST_HT_MENU_ID)
{
// A selection was made from the context menu.
// Use the menu map to get the HT command value
CRDFMenuCommand* theCommand = (CRDFMenuCommand*)(m_MenuCommandMap.GetCommand((int)wParam-FIRST_HT_MENU_ID));
if (theCommand)
{
HT_MenuCmd htCommand = theCommand->GetHTCommand();
HT_DoMenuCmd(m_Pane, htCommand);
}
}
return TRUE;
}
CSelectorDropTarget::CSelectorDropTarget(CSelector* pParent)
{
fd = 0;
m_pParent = pParent;
}
CSelectorDropTarget::~CSelectorDropTarget()
{
delete fd;
}
BOOL CSelectorDropTarget::OnDrop(CWnd* pWnd,
COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
{
CSelector* pSelector = (CSelector*)pWnd;
HT_View theView = pSelector->GetDragButton()->GetHTView();
pSelector->SetDragButton(NULL);
if (pSelector->GetSwitchTimer() != 0)
pSelector->KillSwitchTimer();
if (theView)
{
// Do a drop.
RDFGLOBAL_PerformDrop(pDataObject, HT_TopNode(theView), pSelector->GetDragFraction());
}
/*
if(!pDataObject || !pWnd)
return(FALSE);
#ifdef XP_WIN32
// we only handle text at the moment
if(! (pDataObject->IsDataAvailable(CF_TEXT) || pDataObject->IsDataAvailable(CF_UNICODETEXT)))
return(FALSE);
#else
// we only handle text at the moment
if(!pDataObject->IsDataAvailable(CF_TEXT))
return(FALSE);
#endif
CSelector * cView = (CSelector *) pWnd;
BOOL bUseUnicodeData = FALSE;
// get the data
HGLOBAL hString = pDataObject->GetGlobalData(CF_TEXT);
if(hString == NULL)
return(FALSE);
// get a pointer to the actual bytes
char * pString = (char *) GlobalLock(hString);
if(!pString)
return(FALSE);
m_url = pString;
GlobalUnlock(hString);
if (strnicmp(m_url, "mailto:", 7) == 0) { // drag from mail and new
// Generic brain dead interface to GetUrl.
pSaveContext = new CSaveCX(NULL, "MCF Viewer", pWnd);
// Create the stream which will do the actual work.
#ifndef XP_WIN16
pSaveContext->Create(CSaveCX::IDD, m_pParent);
#elif defined(DEBUG_hyatt) || defined(DEBUG_mhwang) || defined(DEBUG_rjc) || defined(DEBUG_guha)
// TODO -WIND16 Fix the saving of MCF correctly, and stop using static strings
#endif
fd = 0;
NET_StreamClass *pStream = NET_NewStream("Saving MCF file",
MCFSaveWrite,
MCFSaveComplete,
MCFSaveAbort,
MCFSaveReady,
this,
pSaveContext->GetContext());
pSaveContext->SetSecondaryStream(pStream);
// Load it.
URL_Struct *pUrlStruct = NET_CreateURLStruct(m_url, NET_DONT_RELOAD);
pSaveContext->GetUrl(pUrlStruct, FO_CACHE_AND_SAVE_AS, TRUE, FALSE);
}
else
{
CWnd* pWindowHit = m_pParent->ChildWindowFromPoint( point );
if (pWindowHit)
{
CSelectorButton* theButton = (CSelectorButton*)pWindowHit;
CPoint point(-1, -1);
return theButton->GetView()->OnDrop(pDataObject, dropEffect, point);
}
else
{ // create a new work space.
HT_NewWorkspace(m_url.GetBuffer(m_url.GetLength()), m_pParent, m_pParent->GetHTPane());
}
}
*/
return(TRUE);
}
LRESULT CSelector::OnButtonDrag(WPARAM wParam, LPARAM lParam)
{
HWND hWnd = (HWND) lParam;
CWnd *pButton = CWnd::FromHandle(hWnd);
COleDataSource * pDataSource = new COleDataSource;
CSelectorButton* pSelButton = (CSelectorButton*)pButton;
pSelButton->FillInOleDataSource(pDataSource);
// Need to clear the selection, since I use that for dropping stuff.
HT_SetSelection(HT_TopNode(pSelButton->GetHTView()));
// Don't start drag until outside this rect
RECT rectDragStart;
pButton->GetClientRect(&rectDragStart);
pButton->MapWindowPoints(this, &rectDragStart);
DROPEFFECT effect;
CToolbarDropSource * pDropSource = new CToolbarDropSource;
effect=pDataSource->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_SCROLL | DROPEFFECT_NONE,
&rectDragStart, pDropSource);
delete pDropSource;
delete pDataSource;
return 1;
}
DROPEFFECT CSelectorDropTarget::OnDragEnter(CWnd* pWnd,
COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
{
return OnDragOver(pWnd, pDataObject, dwKeyState, point);
}
DROPEFFECT CSelectorDropTarget::OnDragOver(CWnd* pWnd,
COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
{
CSelector* pSelector = (CSelector*)pWnd;
int dragFraction;
CSelectorButton* pButton = pSelector->GetButtonFromPoint(point, dragFraction);
HT_Resource theNode = pButton ? pButton->GetNode() : NULL;
// Give some drag feedback.
DROPEFFECT answer = RDFGLOBAL_TranslateDropAction(theNode, pDataObject, dragFraction);
if (pButton != pSelector->GetDragButton() || dragFraction != pSelector->GetDragFraction())
{
// User is over a different button or different part of the same button
if (pSelector->GetSwitchTimer() != 0)
pSelector->KillSwitchTimer(); // Kill the existing pane switch timer.
pSelector->SetDragButton(pButton);
pSelector->SetDragFraction(dragFraction);
if (answer != DROPEFFECT_NONE && dragFraction == 2) // Set the pane switching timer if the user can drop here.
pSelector->SetSwitchTimer();
else
{
// Kill any menus that are up.
CDropMenu* theLastMenu = CDropMenu::GetLastDropMenu();
if(theLastMenu !=NULL)
{
//we only want one drop menu open at a time, so close the last one if one is
//still open.
theLastMenu->Deactivate();
CDropMenu::SetLastDropMenu(NULL);
}
}
}
return answer;
}
void CSelectorDropTarget::OnDragLeave(CWnd* pWnd)
{
CSelector* pSelector = (CSelector*)pWnd;
pSelector->SetDragButton(NULL);
if (pSelector->GetSwitchTimer() != 0)
{
pSelector->KillSwitchTimer();
}
}
IMPLEMENT_DYNAMIC(CNavSelScrollButton, CButton)
BEGIN_MESSAGE_MAP(CNavSelScrollButton, CButton)
//{{AFX_MSG_MAP(CMainFrame)
// ON_WM_LBUTTONUP()
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CNavSelScrollButton::CNavSelScrollButton(HBITMAP hBmp, int width, int index, int height)
{
m_hbmp = hBmp;
m_width = width;
m_index = index;
m_height = height;
m_selected = FALSE;
}
void CNavSelScrollButton::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
if (lpDrawItemStruct->itemAction == ODA_FOCUS )
return;
if ( m_hbmp ) {
RECT rect;
GetClientRect(&rect);
int index = m_index; // normal state bitmap.
HDC hdcBitmap = ::CreateCompatibleDC( lpDrawItemStruct->hDC );
HBITMAP hbmOld = (HBITMAP) ::SelectObject( hdcBitmap, m_hbmp );
if ((lpDrawItemStruct->itemAction == ODA_SELECT) &&
((lpDrawItemStruct->itemState & ODS_SELECTED) == ODS_SELECTED)) {
if (m_selected) {
m_selected = FALSE;
}
else {
m_selected = TRUE;
index = m_index + 1; // selected state bitmap.
}
}
FEU_TransBlt( lpDrawItemStruct->hDC,
lpDrawItemStruct->rcItem.right - m_width,
lpDrawItemStruct->rcItem.top,
m_width, m_height,
hdcBitmap,
index * m_width, 0 ,WFE_GetUIPalette(GetParentFrame())
);
::SelectObject( hdcBitmap, hbmOld );
ShowWindow(SW_SHOW);
VERIFY( ::DeleteDC( hdcBitmap ));
CRgn pRgn;
pRgn.CreateRectRgn( m_boundBox.left, m_boundBox.top,
m_boundBox.right, m_boundBox.bottom );
GetParent()->ValidateRgn( &pRgn );
pRgn.DeleteObject();
}
}
unsigned int MCFSaveReady(NET_StreamClass *stream)
{
// Get our save context out of the data object.
CSelectorDropTarget* pDropTarget = (CSelectorDropTarget*)stream->data_object;
if (!pDropTarget->fd) {
strcpy(pDropTarget->fileName, WH_TempFileName(xpTemporary, "mcf", ".mcf"));
pDropTarget->fd = new CFile(pDropTarget->fileName, CFile::modeCreate | CFile::modeWrite );
}
return (MAX_WRITE_READY);
}
int MCFSaveWrite(NET_StreamClass *stream, const char *pWriteData, int32 iDataLength)
{
CSelectorDropTarget* pDropTarget = (CSelectorDropTarget*)stream->data_object;
if (!pDropTarget->fd) {
strcpy(pDropTarget->fileName, WH_TempFileName(xpTemporary, "mcf", ".mcf"));
pDropTarget->fd = new CFile(pDropTarget->fileName, CFile::modeCreate | CFile::modeWrite );
}
pDropTarget->fd->Write( pWriteData, (UINT)iDataLength );
// Return the amount written, or error.
return((UINT)iDataLength);
}
void MCFSaveComplete(NET_StreamClass *stream)
{
CSelectorDropTarget* pDropTarget = (CSelectorDropTarget*)stream->data_object;
pDropTarget->fd->Close( );
/*
HT_NewWorkspace(pDropTarget->fileName, pDropTarget->m_pParent, pDropTarget->m_pParent->GetHTPane());
*/
}
void MCFSaveAbort(NET_StreamClass *stream, int iStatus)
{
}