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