| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: splittree.cpp |
| 3 | // Purpose: Classes to achieve a remotely-scrolled tree in a splitter |
| 4 | // window that can be scrolled by a scrolled window higher in the |
| 5 | // hierarchy |
| 6 | // Author: Julian Smart |
| 7 | // Modified by: |
| 8 | // Created: 8/7/2000 |
| 9 | // RCS-ID: $Id$ |
| 10 | // Copyright: (c) Julian Smart |
| 11 | // Licence: wxWindows licence |
| 12 | ///////////////////////////////////////////////////////////////////////////// |
| 13 | |
| 14 | // ============================================================================ |
| 15 | // declarations |
| 16 | // ============================================================================ |
| 17 | |
| 18 | // ---------------------------------------------------------------------------- |
| 19 | // headers |
| 20 | // ---------------------------------------------------------------------------- |
| 21 | #if defined(__GNUG__) && !defined(__APPLE__) |
| 22 | #pragma implementation "splittree.h" |
| 23 | #endif |
| 24 | |
| 25 | // For compilers that support precompilation, includes "wx/wx.h". |
| 26 | #include "wx/wxprec.h" |
| 27 | |
| 28 | #ifdef __BORLANDC__ |
| 29 | #pragma hdrstop |
| 30 | #endif |
| 31 | |
| 32 | // for all others, include the necessary headers (this file is usually all you |
| 33 | // need because it includes almost all "standard" wxWidgets headers) |
| 34 | #ifndef WX_PRECOMP |
| 35 | #include "wx/wx.h" |
| 36 | #endif |
| 37 | |
| 38 | #ifdef __WXMSW__ |
| 39 | #include <windows.h> |
| 40 | #include "wx/msw/winundef.h" |
| 41 | #endif |
| 42 | |
| 43 | #include "wx/gizmos/splittree.h" |
| 44 | #include <math.h> |
| 45 | |
| 46 | /* |
| 47 | * wxRemotelyScrolledTreeCtrl |
| 48 | */ |
| 49 | |
| 50 | #if USE_GENERIC_TREECTRL |
| 51 | IMPLEMENT_CLASS(wxRemotelyScrolledTreeCtrl, wxGenericTreeCtrl) |
| 52 | #else |
| 53 | IMPLEMENT_CLASS(wxRemotelyScrolledTreeCtrl, wxTreeCtrl) |
| 54 | #endif |
| 55 | |
| 56 | #if USE_GENERIC_TREECTRL |
| 57 | BEGIN_EVENT_TABLE(wxRemotelyScrolledTreeCtrl, wxGenericTreeCtrl) |
| 58 | #else |
| 59 | BEGIN_EVENT_TABLE(wxRemotelyScrolledTreeCtrl, wxTreeCtrl) |
| 60 | #endif |
| 61 | EVT_SIZE(wxRemotelyScrolledTreeCtrl::OnSize) |
| 62 | EVT_TREE_ITEM_EXPANDED(wxID_ANY, wxRemotelyScrolledTreeCtrl::OnExpand) |
| 63 | EVT_TREE_ITEM_COLLAPSED(wxID_ANY, wxRemotelyScrolledTreeCtrl::OnExpand) |
| 64 | EVT_SCROLLWIN(wxRemotelyScrolledTreeCtrl::OnScroll) |
| 65 | END_EVENT_TABLE() |
| 66 | |
| 67 | wxRemotelyScrolledTreeCtrl::wxRemotelyScrolledTreeCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pt, |
| 68 | const wxSize& sz, long style): |
| 69 | wxTreeCtrl(parent, id, pt, sz, style) |
| 70 | { |
| 71 | m_companionWindow = NULL; |
| 72 | } |
| 73 | |
| 74 | wxRemotelyScrolledTreeCtrl::~wxRemotelyScrolledTreeCtrl() |
| 75 | { |
| 76 | } |
| 77 | |
| 78 | void wxRemotelyScrolledTreeCtrl::HideVScrollbar() |
| 79 | { |
| 80 | #if defined(__WXMSW__) && USE_GENERIC_TREECTRL |
| 81 | if (!IsKindOf(CLASSINFO(wxGenericTreeCtrl))) |
| 82 | { |
| 83 | ::ShowScrollBar((HWND) GetHWND(), SB_VERT, false); |
| 84 | } |
| 85 | else |
| 86 | #endif |
| 87 | { |
| 88 | // Implicit in overriding SetScrollbars |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | // Number of pixels per user unit (0 or -1 for no scrollbar) |
| 93 | // Length of virtual canvas in user units |
| 94 | // Length of page in user units |
| 95 | #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) |
| 96 | void wxRemotelyScrolledTreeCtrl::SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, |
| 97 | int noUnitsX, int noUnitsY, |
| 98 | int xPos, int yPos, |
| 99 | bool noRefresh) |
| 100 | { |
| 101 | if (IsKindOf(CLASSINFO(wxGenericTreeCtrl))) |
| 102 | { |
| 103 | wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this; |
| 104 | win->wxGenericTreeCtrl::SetScrollbars(pixelsPerUnitX, 0, noUnitsX, 0, xPos, 0, noRefresh); |
| 105 | |
| 106 | wxScrolledWindow* scrolledWindow = GetScrolledWindow(); |
| 107 | if (scrolledWindow) |
| 108 | { |
| 109 | scrolledWindow->SetScrollbars(0, pixelsPerUnitY, 0, noUnitsY, 0, yPos, noRefresh); |
| 110 | } |
| 111 | } |
| 112 | #else |
| 113 | void wxRemotelyScrolledTreeCtrl::SetScrollbars(int WXUNUSED(pixelsPerUnitX), int WXUNUSED(pixelsPerUnitY), |
| 114 | int WXUNUSED(noUnitsX), int WXUNUSED(noUnitsY), |
| 115 | int WXUNUSED(xPos), int WXUNUSED(yPos), |
| 116 | bool WXUNUSED(noRefresh)) |
| 117 | { |
| 118 | #endif |
| 119 | } |
| 120 | |
| 121 | // In case we're using the generic tree control. |
| 122 | #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) |
| 123 | int wxRemotelyScrolledTreeCtrl::GetScrollPos(int orient) const |
| 124 | { |
| 125 | wxScrolledWindow* scrolledWindow = GetScrolledWindow(); |
| 126 | |
| 127 | if (IsKindOf(CLASSINFO(wxGenericTreeCtrl))) |
| 128 | { |
| 129 | wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this; |
| 130 | |
| 131 | if (orient == wxHORIZONTAL) |
| 132 | return win->wxGenericTreeCtrl::GetScrollPos(orient); |
| 133 | else |
| 134 | { |
| 135 | return scrolledWindow->GetScrollPos(orient); |
| 136 | } |
| 137 | } |
| 138 | #else |
| 139 | int wxRemotelyScrolledTreeCtrl::GetScrollPos(int WXUNUSED(orient)) const |
| 140 | { |
| 141 | #endif |
| 142 | return 0; |
| 143 | } |
| 144 | |
| 145 | |
| 146 | // In case we're using the generic tree control. |
| 147 | // Get the view start |
| 148 | void wxRemotelyScrolledTreeCtrl::GetViewStart(int *x, int *y) const |
| 149 | { |
| 150 | wxScrolledWindow* scrolledWindow = GetScrolledWindow(); |
| 151 | |
| 152 | #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) |
| 153 | if (IsKindOf(CLASSINFO(wxGenericTreeCtrl))) |
| 154 | { |
| 155 | |
| 156 | wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this; |
| 157 | int x1, y1, x2, y2; |
| 158 | win->wxGenericTreeCtrl::GetViewStart(& x1, & y1); |
| 159 | * x = x1; * y = y1; |
| 160 | if (!scrolledWindow) |
| 161 | return; |
| 162 | |
| 163 | scrolledWindow->GetViewStart(& x2, & y2); |
| 164 | * y = y2; |
| 165 | } |
| 166 | else |
| 167 | #endif |
| 168 | { |
| 169 | // x is wrong since the horizontal scrollbar is controlled by the |
| 170 | // tree control, but we probably don't need it. |
| 171 | scrolledWindow->GetViewStart(x, y); |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | // In case we're using the generic tree control. |
| 176 | #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) |
| 177 | void wxRemotelyScrolledTreeCtrl::PrepareDC(wxDC& dc) |
| 178 | { |
| 179 | if (IsKindOf(CLASSINFO(wxGenericTreeCtrl))) |
| 180 | { |
| 181 | wxScrolledWindow* scrolledWindow = GetScrolledWindow(); |
| 182 | |
| 183 | wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this; |
| 184 | |
| 185 | int startX, startY; |
| 186 | GetViewStart(& startX, & startY); |
| 187 | |
| 188 | int xppu1, yppu1, xppu2, yppu2; |
| 189 | win->wxGenericTreeCtrl::GetScrollPixelsPerUnit(& xppu1, & yppu1); |
| 190 | scrolledWindow->GetScrollPixelsPerUnit(& xppu2, & yppu2); |
| 191 | |
| 192 | dc.SetDeviceOrigin( -startX * xppu1, -startY * yppu2 ); |
| 193 | // dc.SetUserScale( win->GetScaleX(), win->GetScaleY() ); |
| 194 | } |
| 195 | #else |
| 196 | void wxRemotelyScrolledTreeCtrl::PrepareDC(wxDC& WXUNUSED(dc)) |
| 197 | { |
| 198 | #endif |
| 199 | } |
| 200 | |
| 201 | // Scroll to the given line (in scroll units where each unit is |
| 202 | // the height of an item) |
| 203 | void wxRemotelyScrolledTreeCtrl::ScrollToLine(int WXUNUSED(posHoriz), int posVert) |
| 204 | { |
| 205 | #ifdef __WXMSW__ |
| 206 | #if USE_GENERIC_TREECTRL |
| 207 | if (!IsKindOf(CLASSINFO(wxGenericTreeCtrl))) |
| 208 | #endif |
| 209 | { |
| 210 | UINT sbCode = SB_THUMBPOSITION; |
| 211 | HWND vertScrollBar = 0; |
| 212 | MSWDefWindowProc((WXUINT) WM_VSCROLL, MAKELONG(sbCode, posVert), (WXLPARAM) vertScrollBar); |
| 213 | } |
| 214 | #if USE_GENERIC_TREECTRL |
| 215 | else |
| 216 | #endif |
| 217 | #endif |
| 218 | #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) |
| 219 | { |
| 220 | wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this; |
| 221 | win->Refresh(); |
| 222 | /* Doesn't work yet because scrolling is ignored by Scroll |
| 223 | int xppu, yppu; |
| 224 | wxScrolledWindow* scrolledWindow = GetScrolledWindow(); |
| 225 | if (scrolledWindow) |
| 226 | { |
| 227 | scrolledWindow->GetScrollPixelsPerUnit(& xppu, & yppu); |
| 228 | win->Scroll(-1, posVert*yppu); |
| 229 | } |
| 230 | */ |
| 231 | } |
| 232 | #endif |
| 233 | } |
| 234 | |
| 235 | void wxRemotelyScrolledTreeCtrl::OnSize(wxSizeEvent& event) |
| 236 | { |
| 237 | HideVScrollbar(); |
| 238 | AdjustRemoteScrollbars(); |
| 239 | event.Skip(); |
| 240 | } |
| 241 | |
| 242 | void wxRemotelyScrolledTreeCtrl::OnExpand(wxTreeEvent& event) |
| 243 | { |
| 244 | AdjustRemoteScrollbars(); |
| 245 | event.Skip(); |
| 246 | |
| 247 | // If we don't have this, we get some bits of lines still remaining |
| 248 | if (event.GetEventType() == wxEVT_COMMAND_TREE_ITEM_COLLAPSED) |
| 249 | Refresh(); |
| 250 | |
| 251 | // Pass on the event |
| 252 | if (m_companionWindow) |
| 253 | m_companionWindow->GetEventHandler()->ProcessEvent(event); |
| 254 | } |
| 255 | |
| 256 | // Adjust the containing wxScrolledWindow's scrollbars appropriately |
| 257 | void wxRemotelyScrolledTreeCtrl::AdjustRemoteScrollbars() |
| 258 | { |
| 259 | #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) |
| 260 | if (IsKindOf(CLASSINFO(wxGenericTreeCtrl))) |
| 261 | { |
| 262 | // This is for the generic tree control. |
| 263 | // It calls SetScrollbars which has been overridden |
| 264 | // to adjust the parent scrolled window vertical |
| 265 | // scrollbar. |
| 266 | ((wxGenericTreeCtrl*) this)->AdjustMyScrollbars(); |
| 267 | return; |
| 268 | } |
| 269 | else |
| 270 | #endif |
| 271 | { |
| 272 | // This is for the wxMSW tree control |
| 273 | wxScrolledWindow* scrolledWindow = GetScrolledWindow(); |
| 274 | if (scrolledWindow) |
| 275 | { |
| 276 | wxRect itemRect; |
| 277 | if (GetBoundingRect(GetRootItem(), itemRect)) |
| 278 | { |
| 279 | // Actually, the real height seems to be 1 less than reported |
| 280 | // (e.g. 16 instead of 16) |
| 281 | int itemHeight = itemRect.GetHeight() - 1; |
| 282 | |
| 283 | int w, h; |
| 284 | GetClientSize(&w, &h); |
| 285 | |
| 286 | wxRect rect(0, 0, 0, 0); |
| 287 | CalcTreeSize(rect); |
| 288 | |
| 289 | double f = ((double) (rect.GetHeight()) / (double) itemHeight) ; |
| 290 | int treeViewHeight = (int) ceil(f); |
| 291 | |
| 292 | int scrollPixelsPerLine = itemHeight; |
| 293 | int scrollPos = - (itemRect.y / itemHeight); |
| 294 | |
| 295 | scrolledWindow->SetScrollbars(0, scrollPixelsPerLine, 0, treeViewHeight, 0, scrollPos); |
| 296 | |
| 297 | // Ensure that when a scrollbar becomes hidden or visible, |
| 298 | // the contained window sizes are right. |
| 299 | // Problem: this is called too early (?) |
| 300 | wxSizeEvent event(scrolledWindow->GetSize(), scrolledWindow->GetId()); |
| 301 | scrolledWindow->GetEventHandler()->ProcessEvent(event); |
| 302 | } |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | |
| 308 | // Calculate the area that contains both rectangles |
| 309 | static wxRect CombineRectangles(const wxRect& rect1, const wxRect& rect2) |
| 310 | { |
| 311 | wxRect rect; |
| 312 | |
| 313 | int right1 = rect1.GetRight(); |
| 314 | int bottom1 = rect1.GetBottom(); |
| 315 | int right2 = rect2.GetRight(); |
| 316 | int bottom2 = rect2.GetBottom(); |
| 317 | |
| 318 | wxPoint topLeft = wxPoint(wxMin(rect1.x, rect2.x), wxMin(rect1.y, rect2.y)); |
| 319 | wxPoint bottomRight = wxPoint(wxMax(right1, right2), wxMax(bottom1, bottom2)); |
| 320 | |
| 321 | rect.x = topLeft.x; rect.y = topLeft.y; |
| 322 | rect.SetRight(bottomRight.x); |
| 323 | rect.SetBottom(bottomRight.y); |
| 324 | |
| 325 | return rect; |
| 326 | } |
| 327 | |
| 328 | |
| 329 | // Calculate the tree overall size so we can set the scrollbar |
| 330 | // correctly |
| 331 | void wxRemotelyScrolledTreeCtrl::CalcTreeSize(wxRect& rect) |
| 332 | { |
| 333 | CalcTreeSize(GetRootItem(), rect); |
| 334 | } |
| 335 | |
| 336 | void wxRemotelyScrolledTreeCtrl::CalcTreeSize(const wxTreeItemId& id, wxRect& rect) |
| 337 | { |
| 338 | // More efficient implementation would be to find the last item (but how?) |
| 339 | // Q: is the bounding rect relative to the top of the virtual tree workspace |
| 340 | // or the top of the window? How would we convert? |
| 341 | wxRect itemSize; |
| 342 | if (GetBoundingRect(id, itemSize)) |
| 343 | { |
| 344 | rect = CombineRectangles(rect, itemSize); |
| 345 | } |
| 346 | |
| 347 | void* cookie; |
| 348 | wxTreeItemId childId = GetFirstChild(id, cookie); |
| 349 | while (childId) |
| 350 | { |
| 351 | CalcTreeSize(childId, rect); |
| 352 | childId = GetNextChild(childId, cookie); |
| 353 | } |
| 354 | } |
| 355 | |
| 356 | // Find the scrolled window that contains this control |
| 357 | wxScrolledWindow* wxRemotelyScrolledTreeCtrl::GetScrolledWindow() const |
| 358 | { |
| 359 | wxWindow* parent = wxWindow::GetParent(); |
| 360 | while (parent) |
| 361 | { |
| 362 | if (parent->IsKindOf(CLASSINFO(wxScrolledWindow))) |
| 363 | return (wxScrolledWindow*) parent; |
| 364 | parent = parent->GetParent(); |
| 365 | } |
| 366 | return NULL; |
| 367 | } |
| 368 | |
| 369 | void wxRemotelyScrolledTreeCtrl::OnScroll(wxScrollWinEvent& event) |
| 370 | { |
| 371 | int orient = event.GetOrientation(); |
| 372 | if (orient == wxHORIZONTAL) |
| 373 | { |
| 374 | event.Skip(); |
| 375 | return; |
| 376 | } |
| 377 | wxScrolledWindow* scrollWin = GetScrolledWindow(); |
| 378 | if (!scrollWin) |
| 379 | return; |
| 380 | |
| 381 | int x, y; |
| 382 | scrollWin->GetViewStart(& x, & y); |
| 383 | |
| 384 | ScrollToLine(-1, y); |
| 385 | } |
| 386 | |
| 387 | /* |
| 388 | * wxTreeCompanionWindow |
| 389 | * |
| 390 | * A window displaying values associated with tree control items. |
| 391 | */ |
| 392 | |
| 393 | IMPLEMENT_CLASS(wxTreeCompanionWindow, wxWindow) |
| 394 | |
| 395 | BEGIN_EVENT_TABLE(wxTreeCompanionWindow, wxWindow) |
| 396 | EVT_PAINT(wxTreeCompanionWindow::OnPaint) |
| 397 | EVT_SCROLLWIN(wxTreeCompanionWindow::OnScroll) |
| 398 | EVT_TREE_ITEM_EXPANDED(wxID_ANY, wxTreeCompanionWindow::OnExpand) |
| 399 | EVT_TREE_ITEM_COLLAPSED(wxID_ANY, wxTreeCompanionWindow::OnExpand) |
| 400 | END_EVENT_TABLE() |
| 401 | |
| 402 | wxTreeCompanionWindow::wxTreeCompanionWindow(wxWindow* parent, wxWindowID id, |
| 403 | const wxPoint& pos, |
| 404 | const wxSize& sz, |
| 405 | long style): |
| 406 | wxWindow(parent, id, pos, sz, style) |
| 407 | { |
| 408 | m_treeCtrl = NULL; |
| 409 | } |
| 410 | |
| 411 | void wxTreeCompanionWindow::DrawItem(wxDC& dc, wxTreeItemId id, const wxRect& rect) |
| 412 | { |
| 413 | // TEST CODE |
| 414 | #if 1 |
| 415 | if (m_treeCtrl) |
| 416 | { |
| 417 | wxString text = m_treeCtrl->GetItemText(id); |
| 418 | dc.SetTextForeground(* wxBLACK); |
| 419 | dc.SetBackgroundMode(wxTRANSPARENT); |
| 420 | |
| 421 | int textW, textH; |
| 422 | dc.GetTextExtent(text, & textW, & textH); |
| 423 | |
| 424 | int x = 5; |
| 425 | int y = rect.GetY() + wxMax(0, (rect.GetHeight() - textH) / 2); |
| 426 | |
| 427 | dc.DrawText(text, x, y); |
| 428 | } |
| 429 | #endif |
| 430 | } |
| 431 | |
| 432 | void wxTreeCompanionWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) |
| 433 | { |
| 434 | wxPaintDC dc(this); |
| 435 | |
| 436 | if (!m_treeCtrl) |
| 437 | return; |
| 438 | |
| 439 | wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID); |
| 440 | dc.SetPen(pen); |
| 441 | dc.SetBrush(* wxTRANSPARENT_BRUSH); |
| 442 | wxFont font(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); |
| 443 | dc.SetFont(font); |
| 444 | |
| 445 | wxSize clientSize = GetClientSize(); |
| 446 | wxRect itemRect; |
| 447 | wxTreeItemId h, lastH; |
| 448 | for(h=m_treeCtrl->GetFirstVisibleItem();h;h=m_treeCtrl->GetNextVisible(h)) |
| 449 | { |
| 450 | if (m_treeCtrl->GetBoundingRect(h, itemRect)) |
| 451 | { |
| 452 | int cy = itemRect.GetTop(); |
| 453 | wxRect drawItemRect(0, cy, clientSize.x, itemRect.GetHeight()); |
| 454 | |
| 455 | lastH = h; |
| 456 | |
| 457 | // Draw the actual item |
| 458 | DrawItem(dc, h, drawItemRect); |
| 459 | dc.DrawLine(0, cy, clientSize.x, cy); |
| 460 | } |
| 461 | } |
| 462 | if (lastH.IsOk() && m_treeCtrl->GetBoundingRect(lastH, itemRect)) |
| 463 | { |
| 464 | int cy = itemRect.GetBottom(); |
| 465 | dc.DrawLine(0, cy, clientSize.x, cy); |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | void wxTreeCompanionWindow::OnScroll(wxScrollWinEvent& event) |
| 470 | { |
| 471 | int orient = event.GetOrientation(); |
| 472 | if (orient == wxHORIZONTAL) |
| 473 | { |
| 474 | event.Skip(); |
| 475 | return; |
| 476 | } |
| 477 | if (!m_treeCtrl) |
| 478 | return; |
| 479 | |
| 480 | // TODO: scroll the window physically instead of just refreshing. |
| 481 | Refresh(true); |
| 482 | } |
| 483 | |
| 484 | void wxTreeCompanionWindow::OnExpand(wxTreeEvent& WXUNUSED(event)) |
| 485 | { |
| 486 | // TODO: something more optimized than simply refresh the whole |
| 487 | // window when the tree is expanded/collapsed. Tricky. |
| 488 | Refresh(); |
| 489 | } |
| 490 | |
| 491 | /* |
| 492 | * wxThinSplitterWindow |
| 493 | */ |
| 494 | |
| 495 | IMPLEMENT_CLASS(wxThinSplitterWindow, wxSplitterWindow) |
| 496 | |
| 497 | BEGIN_EVENT_TABLE(wxThinSplitterWindow, wxSplitterWindow) |
| 498 | EVT_SIZE(wxThinSplitterWindow::OnSize) |
| 499 | END_EVENT_TABLE() |
| 500 | |
| 501 | wxThinSplitterWindow::wxThinSplitterWindow(wxWindow* parent, wxWindowID id, |
| 502 | const wxPoint& pos, |
| 503 | const wxSize& sz, |
| 504 | long style): |
| 505 | wxSplitterWindow(parent, id, pos, sz, style) |
| 506 | { |
| 507 | } |
| 508 | |
| 509 | wxThinSplitterWindow::~wxThinSplitterWindow() |
| 510 | { |
| 511 | } |
| 512 | |
| 513 | void wxThinSplitterWindow::SizeWindows() |
| 514 | { |
| 515 | // The client size may have changed inbetween |
| 516 | // the sizing of the first window and the sizing of |
| 517 | // the second. So repeat SizeWindows. |
| 518 | wxSplitterWindow::SizeWindows(); |
| 519 | wxSplitterWindow::SizeWindows(); |
| 520 | } |
| 521 | |
| 522 | // Tests for x, y over sash |
| 523 | bool wxThinSplitterWindow::SashHitTest(int x, int y, int WXUNUSED(tolerance)) |
| 524 | { |
| 525 | return wxSplitterWindow::SashHitTest(x, y, 4); |
| 526 | } |
| 527 | |
| 528 | void wxThinSplitterWindow::DrawSash(wxDC& dc) |
| 529 | { |
| 530 | if ( GetSashPosition() == 0 || !m_windowTwo) |
| 531 | return; |
| 532 | if (GetWindowStyle() & wxSP_NOSASH) |
| 533 | return; |
| 534 | |
| 535 | int w, h; |
| 536 | GetClientSize(&w, &h); |
| 537 | |
| 538 | if ( m_splitMode == wxSPLIT_VERTICAL ) |
| 539 | { |
| 540 | dc.SetPen(* m_facePen); |
| 541 | dc.SetBrush(* m_faceBrush); |
| 542 | int h1 = h-1; |
| 543 | int y1 = 0; |
| 544 | if ( (GetWindowStyleFlag() & wxSP_BORDER) != wxSP_BORDER && (GetWindowStyleFlag() & wxSP_3DBORDER) != wxSP_3DBORDER ) |
| 545 | h1 += 1; // Not sure why this is necessary... |
| 546 | if ( (GetWindowStyleFlag() & wxSP_3DBORDER) == wxSP_3DBORDER) |
| 547 | { |
| 548 | y1 = 2; h1 -= 3; |
| 549 | } |
| 550 | dc.DrawRectangle(GetSashPosition(), y1, GetSashSize(), h1); |
| 551 | } |
| 552 | else |
| 553 | { |
| 554 | dc.SetPen(* m_facePen); |
| 555 | dc.SetBrush(* m_faceBrush); |
| 556 | int w1 = w-1; |
| 557 | int x1 = 0; |
| 558 | if ( (GetWindowStyleFlag() & wxSP_BORDER) != wxSP_BORDER && (GetWindowStyleFlag() & wxSP_3DBORDER) != wxSP_3DBORDER ) |
| 559 | w1 ++; |
| 560 | if ( (GetWindowStyleFlag() & wxSP_3DBORDER) == wxSP_3DBORDER) |
| 561 | { |
| 562 | x1 = 2; w1 -= 3; |
| 563 | } |
| 564 | dc.DrawRectangle(x1, GetSashPosition(), w1, GetSashSize()); |
| 565 | } |
| 566 | |
| 567 | dc.SetPen(wxNullPen); |
| 568 | dc.SetBrush(wxNullBrush); |
| 569 | } |
| 570 | |
| 571 | void wxThinSplitterWindow::OnSize(wxSizeEvent& event) |
| 572 | { |
| 573 | wxSplitterWindow::OnSize(event); |
| 574 | } |
| 575 | |
| 576 | /* |
| 577 | * wxSplitterScrolledWindow |
| 578 | */ |
| 579 | |
| 580 | IMPLEMENT_CLASS(wxSplitterScrolledWindow, wxScrolledWindow) |
| 581 | |
| 582 | BEGIN_EVENT_TABLE(wxSplitterScrolledWindow, wxScrolledWindow) |
| 583 | EVT_SCROLLWIN(wxSplitterScrolledWindow::OnScroll) |
| 584 | EVT_SIZE(wxSplitterScrolledWindow::OnSize) |
| 585 | END_EVENT_TABLE() |
| 586 | |
| 587 | wxSplitterScrolledWindow::wxSplitterScrolledWindow(wxWindow* parent, wxWindowID id, |
| 588 | const wxPoint& pos, |
| 589 | const wxSize& sz, |
| 590 | long style): |
| 591 | wxScrolledWindow(parent, id, pos, sz, style) |
| 592 | { |
| 593 | } |
| 594 | |
| 595 | void wxSplitterScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) |
| 596 | { |
| 597 | wxSize sz = GetClientSize(); |
| 598 | if (GetChildren().GetFirst()) |
| 599 | { |
| 600 | ((wxWindow*) GetChildren().GetFirst()->GetData())->SetSize(0, 0, sz.x, sz.y); |
| 601 | } |
| 602 | } |
| 603 | |
| 604 | void wxSplitterScrolledWindow::OnScroll(wxScrollWinEvent& event) |
| 605 | { |
| 606 | // Ensure that events being propagated back up the window hierarchy |
| 607 | // don't cause an infinite loop |
| 608 | static bool inOnScroll = false; |
| 609 | if (inOnScroll) |
| 610 | { |
| 611 | event.Skip(); |
| 612 | return; |
| 613 | } |
| 614 | inOnScroll = true; |
| 615 | |
| 616 | int orient = event.GetOrientation(); |
| 617 | |
| 618 | int nScrollInc = CalcScrollInc(event); |
| 619 | if (nScrollInc == 0) |
| 620 | { |
| 621 | inOnScroll = false; |
| 622 | return; |
| 623 | } |
| 624 | |
| 625 | if (orient == wxHORIZONTAL) |
| 626 | { |
| 627 | inOnScroll = false; |
| 628 | event.Skip(); |
| 629 | return; |
| 630 | #if 0 |
| 631 | int newPos = m_xScrollPosition + nScrollInc; |
| 632 | SetScrollPos(wxHORIZONTAL, newPos, true ); |
| 633 | #endif |
| 634 | } |
| 635 | else |
| 636 | { |
| 637 | int newPos = m_yScrollPosition + nScrollInc; |
| 638 | SetScrollPos(wxVERTICAL, newPos, true ); |
| 639 | } |
| 640 | |
| 641 | if (orient == wxHORIZONTAL) |
| 642 | { |
| 643 | m_xScrollPosition += nScrollInc; |
| 644 | } |
| 645 | else |
| 646 | { |
| 647 | m_yScrollPosition += nScrollInc; |
| 648 | } |
| 649 | |
| 650 | // Find targets in splitter window and send the event to them |
| 651 | wxNode* node = (wxNode *)GetChildren().GetFirst(); |
| 652 | while (node) |
| 653 | { |
| 654 | wxWindow* child = (wxWindow*) node->GetData(); |
| 655 | if (child->IsKindOf(CLASSINFO(wxSplitterWindow))) |
| 656 | { |
| 657 | wxSplitterWindow* splitter = (wxSplitterWindow*) child; |
| 658 | if (splitter->GetWindow1()) |
| 659 | splitter->GetWindow1()->ProcessEvent(event); |
| 660 | if (splitter->GetWindow2()) |
| 661 | splitter->GetWindow2()->ProcessEvent(event); |
| 662 | break; |
| 663 | } |
| 664 | node = node->GetNext(); |
| 665 | } |
| 666 | |
| 667 | #ifdef __WXMAC__ |
| 668 | m_targetWindow->MacUpdateImmediately() ; |
| 669 | #endif |
| 670 | |
| 671 | inOnScroll = false; |
| 672 | } |
| 673 | |