📄 splittree.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: splittree.cpp
// Purpose: Classes to achieve a remotely-scrolled tree in a splitter
// window that can be scrolled by a scrolled window higher in the
// hierarchy
// Author: Julian Smart
// Modified by:
// Created: 8/7/2000
// RCS-ID: $Id: splittree.cpp,v 1.35 2005/09/23 12:47:48 MR Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#ifdef __WXMSW__
#include <windows.h>
#include "wx/msw/winundef.h"
#endif
#include "wx/gizmos/splittree.h"
#include <math.h>
/*
* wxRemotelyScrolledTreeCtrl
*/
#if USE_GENERIC_TREECTRL
IMPLEMENT_CLASS(wxRemotelyScrolledTreeCtrl, wxGenericTreeCtrl)
#else
IMPLEMENT_CLASS(wxRemotelyScrolledTreeCtrl, wxTreeCtrl)
#endif
#if USE_GENERIC_TREECTRL
BEGIN_EVENT_TABLE(wxRemotelyScrolledTreeCtrl, wxGenericTreeCtrl)
#else
BEGIN_EVENT_TABLE(wxRemotelyScrolledTreeCtrl, wxTreeCtrl)
#endif
EVT_SIZE(wxRemotelyScrolledTreeCtrl::OnSize)
EVT_PAINT(wxRemotelyScrolledTreeCtrl::OnPaint)
EVT_TREE_ITEM_EXPANDED(wxID_ANY, wxRemotelyScrolledTreeCtrl::OnExpand)
EVT_TREE_ITEM_COLLAPSED(wxID_ANY, wxRemotelyScrolledTreeCtrl::OnExpand)
EVT_SCROLLWIN(wxRemotelyScrolledTreeCtrl::OnScroll)
END_EVENT_TABLE()
wxRemotelyScrolledTreeCtrl::wxRemotelyScrolledTreeCtrl(
wxWindow* parent, wxWindowID id, const wxPoint& pt,
const wxSize& sz, long style)
: wxTreeCtrl(parent, id, pt, sz, style & ~wxTR_ROW_LINES)
{
m_companionWindow = NULL;
// We draw the row lines ourself so they match what's done
// by the companion window. That is why the flag is turned
// off above, so wxGenericTreeCtrl doesn't draw them in a
// different colour.
m_drawRowLines = (style & wxTR_ROW_LINES) != 0;
}
wxRemotelyScrolledTreeCtrl::~wxRemotelyScrolledTreeCtrl()
{
}
void wxRemotelyScrolledTreeCtrl::HideVScrollbar()
{
#if defined(__WXMSW__)
#if USE_GENERIC_TREECTRL
if (!IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
#endif
{
::ShowScrollBar((HWND) GetHWND(), SB_VERT, false);
}
#if USE_GENERIC_TREECTRL
else
{
// Implicit in overriding SetScrollbars
}
#endif
#endif
}
// Number of pixels per user unit (0 or -1 for no scrollbar)
// Length of virtual canvas in user units
// Length of page in user units
void wxRemotelyScrolledTreeCtrl::SetScrollbars(
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
int pixelsPerUnitX, int pixelsPerUnitY,
int noUnitsX, int noUnitsY,
int xPos, int yPos,
bool noRefresh
#else
int WXUNUSED(pixelsPerUnitX), int WXUNUSED(pixelsPerUnitY),
int WXUNUSED(noUnitsX), int WXUNUSED(noUnitsY),
int WXUNUSED(xPos), int WXUNUSED(yPos),
bool WXUNUSED(noRefresh)
#endif
)
{
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
{
wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
win->wxGenericTreeCtrl::SetScrollbars(pixelsPerUnitX, pixelsPerUnitY, noUnitsX, 0, xPos, 0, /* noRefresh */ true);
wxScrolledWindow* scrolledWindow = GetScrolledWindow();
if (scrolledWindow)
{
scrolledWindow->SetScrollbars(0, pixelsPerUnitY, 0, noUnitsY, 0, yPos, noRefresh);
}
}
#endif
}
// In case we're using the generic tree control.
int wxRemotelyScrolledTreeCtrl::GetScrollPos(
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
int orient
#else
int WXUNUSED(orient)
#endif
) const
{
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
// this condition fixes extsitence of warning but
wxScrolledWindow* scrolledWindow =
// but GetScrolledWindow is still executed in case internally does something
#endif
GetScrolledWindow();
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
{
wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
if (orient == wxHORIZONTAL)
return win->wxGenericTreeCtrl::GetScrollPos(orient);
else
{
return scrolledWindow->GetScrollPos(orient);
}
}
#endif
return 0;
}
// In case we're using the generic tree control.
// Get the view start
void wxRemotelyScrolledTreeCtrl::GetViewStart(int *x, int *y) const
{
wxScrolledWindow* scrolledWindow = GetScrolledWindow();
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
{
wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
int x1, y1, x2, y2;
win->wxGenericTreeCtrl::GetViewStart(& x1, & y1);
* x = x1; * y = y1;
if (!scrolledWindow)
return;
scrolledWindow->GetViewStart(& x2, & y2);
* y = y2;
}
else
#endif
{
// x is wrong since the horizontal scrollbar is controlled by the
// tree control, but we probably don't need it.
scrolledWindow->GetViewStart(x, y);
}
}
// In case we're using the generic tree control.
void wxRemotelyScrolledTreeCtrl::PrepareDC(
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
wxDC& dc
#else
wxDC& WXUNUSED(dc)
#endif
)
{
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
{
wxScrolledWindow* scrolledWindow = GetScrolledWindow();
wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
int startX, startY;
GetViewStart(& startX, & startY);
int xppu1, yppu1, xppu2, yppu2;
win->wxGenericTreeCtrl::GetScrollPixelsPerUnit(& xppu1, & yppu1);
scrolledWindow->GetScrollPixelsPerUnit(& xppu2, & yppu2);
dc.SetDeviceOrigin( -startX * xppu1, -startY * yppu2 );
// dc.SetUserScale( win->GetScaleX(), win->GetScaleY() );
}
#endif
}
// Scroll to the given line (in scroll units where each unit is
// the height of an item)
void wxRemotelyScrolledTreeCtrl::ScrollToLine(int WXUNUSED(posHoriz), int posVert)
{
#ifdef __WXMSW__
#if USE_GENERIC_TREECTRL
if (!IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
#endif // USE_GENERIC_TREECTRL
{
UINT sbCode = SB_THUMBPOSITION;
HWND vertScrollBar = 0;
MSWDefWindowProc((WXUINT) WM_VSCROLL, MAKELONG(sbCode, posVert), (WXLPARAM) vertScrollBar);
}
#if USE_GENERIC_TREECTRL
else
#endif // USE_GENERIC_TREECTRL
#endif // __WXMSW__
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
{
wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
win->Refresh();
/* Doesn't work yet because scrolling is ignored by Scroll
int xppu, yppu;
wxScrolledWindow* scrolledWindow = GetScrolledWindow();
if (scrolledWindow)
{
scrolledWindow->GetScrollPixelsPerUnit(& xppu, & yppu);
win->Scroll(-1, posVert*yppu);
}
*/
}
#endif // USE_GENERIC_TREECTRL || !defined(__WXMSW__)
wxUnusedVar(posVert);
}
void wxRemotelyScrolledTreeCtrl::OnSize(wxSizeEvent& event)
{
HideVScrollbar();
AdjustRemoteScrollbars();
event.Skip();
}
void wxRemotelyScrolledTreeCtrl::OnExpand(wxTreeEvent& event)
{
AdjustRemoteScrollbars();
event.Skip();
// If we don't have this, we get some bits of lines still remaining
if (event.GetEventType() == wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
Refresh();
// Pass on the event
if (m_companionWindow)
m_companionWindow->GetEventHandler()->ProcessEvent(event);
}
void wxRemotelyScrolledTreeCtrl::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
wxTreeCtrl::OnPaint(event);
if (! m_drawRowLines)
return;
// Reset the device origin since it may have been set
dc.SetDeviceOrigin(0, 0);
wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID);
dc.SetPen(pen);
dc.SetBrush(* wxTRANSPARENT_BRUSH);
wxSize clientSize = GetClientSize();
wxRect itemRect;
wxTreeItemId h, lastH;
for (h=GetFirstVisibleItem();
h.IsOk();
h=GetNextVisible(h))
{
if (GetBoundingRect(h, itemRect))
{
int cy = itemRect.GetTop();
dc.DrawLine(0, cy, clientSize.x, cy);
lastH = h;
}
if (! IsVisible(h))
break;
}
if (lastH.IsOk() && GetBoundingRect(lastH, itemRect))
{
int cy = itemRect.GetBottom();
dc.DrawLine(0, cy, clientSize.x, cy);
}
}
// Adjust the containing wxScrolledWindow's scrollbars appropriately
void wxRemotelyScrolledTreeCtrl::AdjustRemoteScrollbars()
{
#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
{
// This is for the generic tree control.
// It calls SetScrollbars which has been overridden
// to adjust the parent scrolled window vertical
// scrollbar.
((wxGenericTreeCtrl*) this)->AdjustMyScrollbars();
return;
}
else
#endif
{
// This is for the wxMSW tree control
wxScrolledWindow* scrolledWindow = GetScrolledWindow();
if (scrolledWindow)
{
wxRect itemRect;
if (GetBoundingRect(GetFirstVisibleItem(), itemRect))
{
// Actually, the real height seems to be 1 less than reported
// (e.g. 16 instead of 16)
int itemHeight = itemRect.GetHeight() - 1;
int w, h;
GetClientSize(&w, &h);
wxRect rect(0, 0, 0, 0);
CalcTreeSize(rect);
double f = ((double) (rect.GetHeight()) / (double) itemHeight) ;
int treeViewHeight = (int) ceil(f);
int scrollPixelsPerLine = itemHeight;
int scrollPos = - (itemRect.y / itemHeight);
scrolledWindow->SetScrollbars(0, scrollPixelsPerLine, 0, treeViewHeight, 0, scrollPos);
// Ensure that when a scrollbar becomes hidden or visible,
// the contained window sizes are right.
// Problem: this is called too early (?)
wxSizeEvent event(scrolledWindow->GetSize(), scrolledWindow->GetId());
scrolledWindow->GetEventHandler()->ProcessEvent(event);
}
}
}
}
// Calculate the area that contains both rectangles
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -