]> git.saurik.com Git - wxWidgets.git/blob - src/generic/splitter.cpp
Added wxAccelerationTable class
[wxWidgets.git] / src / generic / splitter.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: splitter.cpp
3 // Purpose: wxSplitterWindow implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "splitter.h"
14 // #pragma interface
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/wx.h"
26 #endif
27
28 #include <math.h>
29 #include <stdlib.h>
30
31 #include "wx/string.h"
32 #include "wx/splitter.h"
33 #include "wx/dcscreen.h"
34
35 #if !USE_SHARED_LIBRARY
36 IMPLEMENT_DYNAMIC_CLASS(wxSplitterWindow, wxWindow)
37
38 BEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow)
39 EVT_PAINT(wxSplitterWindow::OnPaint)
40 EVT_SIZE(wxSplitterWindow::OnSize)
41 EVT_MOUSE_EVENTS(wxSplitterWindow::OnMouseEvent)
42 END_EVENT_TABLE()
43 #endif
44
45 wxSplitterWindow::wxSplitterWindow(void)
46 {
47 m_splitMode = wxSPLIT_VERTICAL;
48 m_windowOne = NULL;
49 m_windowTwo = NULL;
50 m_dragMode = wxSPLIT_DRAG_NONE;
51 m_oldX = 0;
52 m_oldY = 0;
53 m_firstX = 0;
54 m_firstY = 0;
55 m_sashSize = 7;
56 m_borderSize = 2;
57 m_sashPosition = 0;
58 m_sashCursorWE = NULL;
59 m_sashCursorNS = NULL;
60 m_sashTrackerPen = NULL;
61 m_lightShadowPen = NULL;
62 m_mediumShadowPen = NULL;
63 m_darkShadowPen = NULL;
64 m_faceBrush = NULL;
65 m_facePen = NULL;
66 m_hilightPen = NULL;
67 m_minimumPaneSize = 0;
68 }
69
70 wxSplitterWindow::wxSplitterWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos,
71 const wxSize& size, long style, const wxString& name)
72 :wxWindow(parent, id, pos, size, style, name)
73 {
74 m_splitMode = wxSPLIT_VERTICAL;
75 m_windowOne = NULL;
76 m_windowTwo = NULL;
77 m_dragMode = wxSPLIT_DRAG_NONE;
78 m_oldX = 0;
79 m_oldY = 0;
80 m_firstX = 0;
81 m_firstY = 0;
82 m_sashSize = 7;
83 m_borderSize = 2;
84 m_sashPosition = 0;
85 m_minimumPaneSize = 0;
86 m_sashCursorWE = new wxCursor(wxCURSOR_SIZEWE);
87 m_sashCursorNS = new wxCursor(wxCURSOR_SIZENS);
88 m_sashTrackerPen = new wxPen(*wxBLACK, 2, wxSOLID);
89 m_lightShadowPen = NULL;
90 m_mediumShadowPen = NULL;
91 m_darkShadowPen = NULL;
92 m_faceBrush = NULL;
93 m_facePen = NULL;
94 m_hilightPen = NULL;
95
96 if ( style & wxSP_3D )
97 {
98 m_borderSize = 2;
99 m_sashSize = 7;
100 }
101 else if ( style & wxSP_BORDER )
102 {
103 m_borderSize = 1;
104 m_sashSize = 3;
105 }
106 else
107 {
108 m_borderSize = 0;
109 m_sashSize = 3;
110 }
111
112 // Eventually, we'll respond to colour change messages
113 InitColours();
114
115 SetDoubleClick(TRUE);
116
117 // For debugging purposes, to see the background.
118 // SetBackground(wxBLUE_BRUSH);
119 }
120
121 wxSplitterWindow::~wxSplitterWindow(void)
122 {
123 delete m_sashCursorWE;
124 delete m_sashCursorNS;
125 delete m_sashTrackerPen;
126 delete m_lightShadowPen;
127 delete m_darkShadowPen;
128 delete m_mediumShadowPen;
129 delete m_hilightPen;
130 delete m_facePen;
131 delete m_faceBrush;
132 }
133
134 void wxSplitterWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
135 {
136 wxPaintDC dc(this);
137
138 if ( m_borderSize > 0 )
139 DrawBorders(dc);
140 DrawSash(dc);
141 }
142
143 void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
144 {
145 long x, y;
146 event.Position(&x, &y);
147
148 if (event.LeftDown())
149 {
150 if ( SashHitTest(x, y) )
151 {
152 CaptureMouse();
153
154 // Required for X to specify that
155 // that we wish to draw on top of all windows
156 // - and we optimise by specifying the area
157 // for creating the overlap window.
158 wxScreenDC::StartDrawingOnTop(this);
159
160 // We don't say we're dragging yet; we leave that
161 // decision for the Dragging() branch, to ensure
162 // the user has dragged a little bit.
163 m_dragMode = wxSPLIT_DRAG_LEFT_DOWN;
164 m_firstX = x;
165 m_firstY = y;
166 }
167 }
168 else if ( event.LeftUp() && m_dragMode == wxSPLIT_DRAG_LEFT_DOWN )
169 {
170 // Wasn't a proper drag
171 ReleaseMouse();
172 wxScreenDC::EndDrawingOnTop();
173 m_dragMode = wxSPLIT_DRAG_NONE;
174
175 SetCursor(*wxSTANDARD_CURSOR);
176 }
177 else if (event.LeftUp() && m_dragMode == wxSPLIT_DRAG_DRAGGING)
178 {
179 // We can stop dragging now and see what we've got.
180 m_dragMode = wxSPLIT_DRAG_NONE;
181 ReleaseMouse();
182 // Erase old tracker
183 DrawSashTracker(m_oldX, m_oldY);
184
185 // End drawing on top (frees the window used for drawing
186 // over the screen)
187 wxScreenDC::EndDrawingOnTop();
188
189 int w, h;
190 GetClientSize(&w, &h);
191 if ( m_splitMode == wxSPLIT_VERTICAL )
192 {
193 // First check if we should veto this resize because
194 // the pane size is too small
195 if ( wxMax(x, 0) < m_minimumPaneSize || wxMax((w - x), 0) < m_minimumPaneSize)
196 return;
197
198 if ( x <= 4 )
199 {
200 // We remove the first window from the view
201 wxWindow *removedWindow = m_windowOne;
202 m_windowOne = m_windowTwo;
203 m_windowTwo = NULL;
204
205 OnUnsplit(removedWindow);
206 m_sashPosition = 0;
207 }
208 else if ( x >= (w - 4) )
209 {
210 // We remove the second window from the view
211 wxWindow *removedWindow = m_windowTwo;
212 m_windowTwo = NULL;
213 OnUnsplit(removedWindow);
214 m_sashPosition = 0;
215 }
216 else
217 {
218 m_sashPosition = x;
219 }
220 }
221 else
222 {
223 // First check if we should veto this resize because
224 // the pane size is too small
225 if ( wxMax(y, 0) < m_minimumPaneSize || wxMax((h - y), 0) < m_minimumPaneSize)
226 return;
227
228 if ( y <= 4 )
229 {
230 // We remove the first window from the view
231 wxWindow *removedWindow = m_windowOne;
232 m_windowOne = m_windowTwo;
233 m_windowTwo = NULL;
234
235 OnUnsplit(removedWindow);
236 m_sashPosition = 0;
237 }
238 else if ( y >= (h - 4) )
239 {
240 // We remove the second window from the view
241 wxWindow *removedWindow = m_windowTwo;
242 m_windowTwo = NULL;
243 OnUnsplit(removedWindow);
244 m_sashPosition = 0;
245 }
246 else
247 {
248 m_sashPosition = y;
249 }
250 }
251 SizeWindows();
252 }
253 else if (event.Moving() && !event.Dragging())
254 {
255 // Just change the cursor if required
256 if ( SashHitTest(x, y) )
257 {
258 if ( m_splitMode == wxSPLIT_VERTICAL )
259 {
260 SetCursor(*m_sashCursorWE);
261 }
262 else
263 {
264 SetCursor(*m_sashCursorNS);
265 }
266 }
267 else
268 {
269 SetCursor(*wxSTANDARD_CURSOR);
270 }
271 }
272 else if ( (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) ||
273 (event.Dragging() && SashHitTest(x, y, 4)) )
274 {
275 if ( m_splitMode == wxSPLIT_VERTICAL )
276 {
277 SetCursor(*m_sashCursorWE);
278 }
279 else
280 {
281 SetCursor(*m_sashCursorNS);
282 }
283
284 // Detect that this is really a drag: we've moved more than 1 pixel either way
285 if ((m_dragMode == wxSPLIT_DRAG_LEFT_DOWN) &&
286 // (abs((int)x - m_firstX) > 1 || abs((int)y - m_firstY) > 1) )
287 (abs((int)x - m_firstX) > 0 || abs((int)y - m_firstY) > 1) )
288 {
289 m_dragMode = wxSPLIT_DRAG_DRAGGING;
290 DrawSashTracker(x, y);
291 }
292 else
293 {
294 if ( m_dragMode == wxSPLIT_DRAG_DRAGGING )
295 {
296 // Erase old tracker
297 DrawSashTracker(m_oldX, m_oldY);
298
299 // Draw new one
300 DrawSashTracker(x, y);
301 }
302 }
303 m_oldX = x;
304 m_oldY = y;
305 }
306 else if ( event.LeftDClick() )
307 {
308 OnDoubleClickSash(x, y);
309 }
310 else
311 {
312 }
313 }
314
315 void wxSplitterWindow::OnSize(wxSizeEvent& WXUNUSED(event))
316 {
317 int cw, ch;
318 GetClientSize( &cw, &ch );
319 if ( m_windowTwo )
320 {
321 if ( m_splitMode == wxSPLIT_VERTICAL )
322 {
323 if ( m_sashPosition >= (cw - 5) )
324 m_sashPosition = wxMax(10, cw - 40);
325 }
326 if ( m_splitMode == wxSPLIT_HORIZONTAL )
327 {
328 if ( m_sashPosition >= (ch - 5) )
329 m_sashPosition = wxMax(10, ch - 40);
330 }
331 }
332 SizeWindows();
333 }
334
335 bool wxSplitterWindow::SashHitTest(int x, int y, int tolerance)
336 {
337 if ( m_windowTwo == NULL || m_sashPosition == 0)
338 return FALSE; // No sash
339
340 if ( m_splitMode == wxSPLIT_VERTICAL )
341 {
342 if ( (x >= m_sashPosition - tolerance) && (x <= m_sashPosition + m_sashSize + tolerance) )
343 return TRUE;
344 else
345 return FALSE;
346 }
347 else
348 {
349 if ( (y >= (m_sashPosition- tolerance)) && (y <= (m_sashPosition + m_sashSize + tolerance)) )
350 return TRUE;
351 else
352 return FALSE;
353 }
354
355 return FALSE;
356 }
357
358 // Draw 3D effect borders
359 void wxSplitterWindow::DrawBorders(wxDC& dc)
360 {
361 int w, h;
362 GetClientSize(&w, &h);
363
364 if ( GetWindowStyleFlag() & wxSP_3D )
365 {
366 dc.SetPen(*m_mediumShadowPen);
367 dc.DrawLine(0, 0, w-1, 0);
368 dc.DrawLine(0, 0, 0, h - 1);
369
370 dc.SetPen(*m_darkShadowPen);
371 dc.DrawLine(1, 1, w-2, 1);
372 dc.DrawLine(1, 1, 1, h-2);
373
374 dc.SetPen(*m_hilightPen);
375 dc.DrawLine(0, h-1, w-1, h-1);
376 dc.DrawLine(w-1, 0, w-1, h); // Surely the maximum y pos. should be h - 1.
377 /// Anyway, h is required for MSW.
378
379 dc.SetPen(*m_lightShadowPen);
380 dc.DrawLine(w-2, 1, w-2, h-2); // Right hand side
381 dc.DrawLine(1, h-2, w-1, h-2); // Bottom
382 }
383 else if ( GetWindowStyleFlag() & wxSP_BORDER )
384 {
385 dc.SetBrush(*wxTRANSPARENT_BRUSH);
386 dc.SetPen(*wxBLACK_PEN);
387 dc.DrawRectangle(0, 0, w-1, h-1);
388 }
389
390 dc.SetPen(wxNullPen);
391 dc.SetBrush(wxNullBrush);
392 }
393
394 // Draw the sash
395 void wxSplitterWindow::DrawSash(wxDC& dc)
396 {
397 if ( m_sashPosition == 0 || !m_windowTwo)
398 return;
399
400 int w, h;
401 GetClientSize(&w, &h);
402
403 if ( GetWindowStyleFlag() & wxSP_3D )
404 {
405 if ( m_splitMode == wxSPLIT_VERTICAL )
406 {
407 dc.SetPen(*m_facePen);
408 dc.SetBrush(*m_faceBrush);
409 dc.DrawRectangle(m_sashPosition + 2, 0, m_sashSize - 4, h);
410
411 dc.SetBrush(*wxTRANSPARENT_BRUSH);
412
413 dc.SetPen(*m_lightShadowPen);
414 dc.DrawLine(m_sashPosition, 1, m_sashPosition, h-2);
415
416 dc.SetPen(*m_hilightPen);
417 dc.DrawLine(m_sashPosition+1, 0, m_sashPosition+1, h);
418
419 dc.SetPen(*m_mediumShadowPen);
420 dc.DrawLine(m_sashPosition+m_sashSize-2, 1, m_sashPosition+m_sashSize-2, h-1);
421
422 dc.SetPen(*m_darkShadowPen);
423 dc.DrawLine(m_sashPosition+m_sashSize-1, 2, m_sashPosition+m_sashSize-1, h-2);
424 }
425 else
426 {
427 dc.SetPen(*m_facePen);
428 dc.SetBrush(*m_faceBrush);
429 dc.DrawRectangle(0, m_sashPosition + 2, w, m_sashSize - 4);
430
431 dc.SetBrush(*wxTRANSPARENT_BRUSH);
432
433 dc.SetPen(*m_lightShadowPen);
434 dc.DrawLine(1, m_sashPosition, w-2, m_sashPosition);
435
436 dc.SetPen(*m_hilightPen);
437 dc.DrawLine(0, m_sashPosition+1, w, m_sashPosition+1);
438
439 dc.SetPen(*m_mediumShadowPen);
440 dc.DrawLine(1, m_sashPosition+m_sashSize-2, w-1, m_sashPosition+m_sashSize-2);
441
442 dc.SetPen(*m_darkShadowPen);
443 dc.DrawLine(2, m_sashPosition+m_sashSize-1, w-2, m_sashPosition+m_sashSize-1);
444 }
445 }
446 else
447 {
448 if ( m_splitMode == wxSPLIT_VERTICAL )
449 {
450 dc.SetPen(*wxBLACK_PEN);
451 dc.SetBrush(*wxBLACK_BRUSH);
452 int h1 = h-1;
453 if ( (GetWindowStyleFlag() & wxSP_BORDER) != wxSP_BORDER )
454 h1 += 1; // Not sure why this is necessary...
455 dc.DrawRectangle(m_sashPosition, 0, m_sashSize, h1);
456 }
457 else
458 {
459 dc.SetPen(*wxBLACK_PEN);
460 dc.SetBrush(*wxBLACK_BRUSH);
461 int w1 = w-1;
462 if ( (GetWindowStyleFlag() & wxSP_BORDER) != wxSP_BORDER )
463 w1 ++;
464
465 dc.DrawRectangle(0, m_sashPosition, w1, m_sashSize);
466 }
467
468 }
469
470 dc.SetPen(wxNullPen);
471 dc.SetBrush(wxNullBrush);
472 }
473
474 // Draw the sash tracker (for whilst moving the sash)
475 void wxSplitterWindow::DrawSashTracker(int x, int y)
476 {
477 int w, h;
478 GetClientSize(&w, &h);
479
480 wxScreenDC screenDC;
481 int x1, y1;
482 int x2, y2;
483
484 if ( m_splitMode == wxSPLIT_VERTICAL )
485 {
486 x1 = x; y1 = 2;
487 x2 = x; y2 = h-2;
488
489 if ( x1 > w )
490 {
491 x1 = w; x2 = w;
492 }
493 else if ( x1 < 0 )
494 {
495 x1 = 0; x2 = 0;
496 }
497 }
498 else
499 {
500 x1 = 2; y1 = y;
501 x2 = w-2; y2 = y;
502
503 if ( y1 > h )
504 {
505 y1 = h;
506 y2 = h;
507 }
508 else if ( y1 < 0 )
509 {
510 y1 = 0;
511 y2 = 0;
512 }
513 }
514
515 ClientToScreen(&x1, &y1);
516 ClientToScreen(&x2, &y2);
517
518 screenDC.SetLogicalFunction(wxXOR);
519 screenDC.SetPen(*m_sashTrackerPen);
520 screenDC.SetBrush(*wxTRANSPARENT_BRUSH);
521
522 screenDC.DrawLine(x1, y1, x2, y2);
523
524 screenDC.SetLogicalFunction(wxCOPY);
525
526 screenDC.SetPen(wxNullPen);
527 screenDC.SetBrush(wxNullBrush);
528 }
529
530 // Position and size subwindows.
531 // Note that the border size applies to each subwindow, not
532 // including the edges next to the sash.
533 void wxSplitterWindow::SizeWindows(void)
534 {
535 int w, h;
536 GetClientSize(&w, &h);
537
538 if ( m_windowOne && !m_windowTwo )
539 {
540 m_windowOne->SetSize(m_borderSize, m_borderSize, w - 2*m_borderSize, h - 2*m_borderSize);
541 }
542 else if ( m_windowOne && m_windowTwo )
543 {
544 if (m_splitMode == wxSPLIT_VERTICAL)
545 {
546 int x1 = m_borderSize;
547 int y1 = m_borderSize;
548 int w1 = m_sashPosition - m_borderSize;
549 int h1 = h - 2*m_borderSize;
550
551 int x2 = m_sashPosition + m_sashSize;
552 int y2 = m_borderSize;
553 int w2 = w - 2*m_borderSize - m_sashSize - w1;
554 int h2 = h - 2*m_borderSize;
555
556 m_windowOne->SetSize(x1, y1,
557 w1, h1);
558 m_windowTwo->SetSize(x2, y2,
559 w2, h2);
560 }
561 else
562 {
563 m_windowOne->SetSize(m_borderSize, m_borderSize,
564 w - 2*m_borderSize, m_sashPosition - m_borderSize);
565 m_windowTwo->SetSize(m_borderSize, m_sashPosition + m_sashSize,
566 w - 2*m_borderSize, h - 2*m_borderSize - m_sashSize - (m_sashPosition - m_borderSize));
567 }
568 }
569 wxClientDC dc(this);
570 DrawBorders(dc);
571 DrawSash(dc);
572 }
573
574 // Set pane for unsplit window
575 void wxSplitterWindow::Initialize(wxWindow *window)
576 {
577 m_windowOne = window;
578 m_windowTwo = NULL;
579 m_sashPosition = 0;
580 }
581
582 // Associates the given window with window 2, drawing the appropriate sash
583 // and changing the split mode.
584 // Does nothing and returns FALSE if the window is already split.
585 bool wxSplitterWindow::SplitVertically(wxWindow *window1, wxWindow *window2, int sashPosition)
586 {
587 if ( IsSplit() )
588 return FALSE;
589
590 m_splitMode = wxSPLIT_VERTICAL;
591 m_windowOne = window1;
592 m_windowTwo = window2;
593 if ( sashPosition == -1 )
594 m_sashPosition = 100;
595 else
596 m_sashPosition = sashPosition;
597
598 SizeWindows();
599
600 return TRUE;
601 }
602
603 bool wxSplitterWindow::SplitHorizontally(wxWindow *window1, wxWindow *window2, int sashPosition)
604 {
605 if ( IsSplit() )
606 return FALSE;
607
608 m_splitMode = wxSPLIT_HORIZONTAL;
609 m_windowOne = window1;
610 m_windowTwo = window2;
611 if ( sashPosition == -1 )
612 m_sashPosition = 100;
613 else
614 m_sashPosition = sashPosition;
615
616 SizeWindows();
617
618 return TRUE;
619 }
620
621
622 // Remove the specified (or second) window from the view
623 // Doesn't actually delete the window.
624 bool wxSplitterWindow::Unsplit(wxWindow *toRemove)
625 {
626 if ( ! IsSplit() )
627 return FALSE;
628
629 if ( toRemove == NULL || toRemove == m_windowTwo)
630 {
631 wxWindow *win = m_windowTwo ;
632 m_windowTwo = NULL;
633 m_sashPosition = 0;
634 OnUnsplit(win);
635 SizeWindows();
636 }
637 else if ( toRemove == m_windowOne )
638 {
639 wxWindow *win = m_windowOne ;
640 m_windowOne = m_windowTwo;
641 m_windowTwo = NULL;
642 m_sashPosition = 0;
643 OnUnsplit(win);
644 SizeWindows();
645 }
646 else
647 return FALSE;
648
649 return TRUE;
650 }
651
652 void wxSplitterWindow::SetSashPosition(int position, bool redraw)
653 {
654 m_sashPosition = position;
655
656 if ( redraw )
657 {
658 SizeWindows();
659 }
660 }
661
662 // Called when the sash is double-clicked.
663 // The default behaviour is to remove the sash if the
664 // minimum pane size is zero.
665 void wxSplitterWindow::OnDoubleClickSash(int WXUNUSED(x), int WXUNUSED(y) )
666 {
667 if ( GetMinimumPaneSize() == 0 )
668 {
669 Unsplit();
670 }
671 }
672
673 // Initialize colours
674 void wxSplitterWindow::InitColours(void)
675 {
676 if ( m_facePen )
677 delete m_facePen;
678 if ( m_faceBrush )
679 delete m_faceBrush;
680 if ( m_mediumShadowPen )
681 delete m_mediumShadowPen;
682 if ( m_darkShadowPen )
683 delete m_darkShadowPen;
684 if ( m_lightShadowPen )
685 delete m_lightShadowPen;
686 if ( m_hilightPen )
687 delete m_hilightPen;
688
689 // Shadow colours
690 #if defined(__WIN95__)
691 // COLORREF ref = ::GetSysColor(COLOR_3DFACE); // Normally light grey
692 wxColour faceColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
693 m_facePen = new wxPen(faceColour, 1, wxSOLID);
694 m_faceBrush = new wxBrush(faceColour, wxSOLID);
695
696 // ref = ::GetSysColor(COLOR_3DSHADOW); // Normally dark grey
697 wxColour mediumShadowColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW));
698 m_mediumShadowPen = new wxPen(mediumShadowColour, 1, wxSOLID);
699
700 // ref = ::GetSysColor(COLOR_3DDKSHADOW); // Normally black
701 wxColour darkShadowColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DDKSHADOW));
702 m_darkShadowPen = new wxPen(darkShadowColour, 1, wxSOLID);
703
704 // ref = ::GetSysColor(COLOR_3DLIGHT); // Normally light grey
705 wxColour lightShadowColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT));
706 m_lightShadowPen = new wxPen(lightShadowColour, 1, wxSOLID);
707
708 // ref = ::GetSysColor(COLOR_3DHILIGHT); // Normally white
709 wxColour hilightColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT));
710 m_hilightPen = new wxPen(hilightColour, 1, wxSOLID);
711 #else
712 m_facePen = new wxPen("LIGHT GREY", 1, wxSOLID);
713 m_faceBrush = new wxBrush("LIGHT GREY", wxSOLID);
714 m_mediumShadowPen = new wxPen("GREY", 1, wxSOLID);
715 m_darkShadowPen = new wxPen("BLACK", 1, wxSOLID);
716 m_lightShadowPen = new wxPen("LIGHT GREY", 1, wxSOLID);
717 m_hilightPen = new wxPen("WHITE", 1, wxSOLID);
718 #endif
719 }
720