replace wxDocument::GetPrintableName(wxString&) and wxDocManager::MakeDefaultName...
[wxWidgets.git] / src / common / gdicmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/gdicmn.cpp
3 // Purpose: Common GDI classes
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include "wx/gdicmn.h"
20 #include "wx/gdiobj.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/log.h"
24 #include "wx/pen.h"
25 #include "wx/brush.h"
26 #include "wx/palette.h"
27 #include "wx/icon.h"
28 #include "wx/iconbndl.h"
29 #include "wx/cursor.h"
30 #include "wx/settings.h"
31 #include "wx/bitmap.h"
32 #include "wx/colour.h"
33 #include "wx/font.h"
34 #endif
35
36
37 IMPLEMENT_DYNAMIC_CLASS(wxGDIObject, wxObject)
38
39
40 WXDLLIMPEXP_DATA_CORE(wxBrushList*) wxTheBrushList;
41 WXDLLIMPEXP_DATA_CORE(wxFontList*) wxTheFontList;
42 WXDLLIMPEXP_DATA_CORE(wxPenList*) wxThePenList;
43
44 WXDLLIMPEXP_DATA_CORE(wxColourDatabase*) wxTheColourDatabase;
45
46 WXDLLIMPEXP_DATA_CORE(wxBitmap) wxNullBitmap;
47 WXDLLIMPEXP_DATA_CORE(wxBrush) wxNullBrush;
48 WXDLLIMPEXP_DATA_CORE(wxColour) wxNullColour;
49 WXDLLIMPEXP_DATA_CORE(wxCursor) wxNullCursor;
50 WXDLLIMPEXP_DATA_CORE(wxFont) wxNullFont;
51 WXDLLIMPEXP_DATA_CORE(wxIcon) wxNullIcon;
52 WXDLLIMPEXP_DATA_CORE(wxPen) wxNullPen;
53 #if wxUSE_PALETTE
54 WXDLLIMPEXP_DATA_CORE(wxPalette) wxNullPalette;
55 #endif
56 WXDLLIMPEXP_DATA_CORE(wxIconBundle) wxNullIconBundle;
57
58 const wxSize wxDefaultSize(wxDefaultCoord, wxDefaultCoord);
59 const wxPoint wxDefaultPosition(wxDefaultCoord, wxDefaultCoord);
60
61 #if wxUSE_EXTENDED_RTTI
62
63 // wxPoint
64
65 template<> void wxStringReadValue(const wxString &s , wxPoint &data )
66 {
67 wxSscanf(s, wxT("%d,%d"), &data.x , &data.y ) ;
68 }
69
70 template<> void wxStringWriteValue(wxString &s , const wxPoint &data )
71 {
72 s = wxString::Format(wxT("%d,%d"), data.x , data.y ) ;
73 }
74
75 wxCUSTOM_TYPE_INFO(wxPoint, wxToStringConverter<wxPoint> , wxFromStringConverter<wxPoint>)
76
77 template<> void wxStringReadValue(const wxString &s , wxSize &data )
78 {
79 wxSscanf(s, wxT("%d,%d"), &data.x , &data.y ) ;
80 }
81
82 template<> void wxStringWriteValue(wxString &s , const wxSize &data )
83 {
84 s = wxString::Format(wxT("%d,%d"), data.x , data.y ) ;
85 }
86
87 wxCUSTOM_TYPE_INFO(wxSize, wxToStringConverter<wxSize> , wxFromStringConverter<wxSize>)
88
89 #endif
90
91 wxRect::wxRect(const wxPoint& point1, const wxPoint& point2)
92 {
93 x = point1.x;
94 y = point1.y;
95 width = point2.x - point1.x;
96 height = point2.y - point1.y;
97
98 if (width < 0)
99 {
100 width = -width;
101 x = point2.x;
102 }
103 width++;
104
105 if (height < 0)
106 {
107 height = -height;
108 y = point2.y;
109 }
110 height++;
111 }
112
113 wxRect& wxRect::Union(const wxRect& rect)
114 {
115 // ignore empty rectangles: union with an empty rectangle shouldn't extend
116 // this one to (0, 0)
117 if ( !width || !height )
118 {
119 *this = rect;
120 }
121 else if ( rect.width && rect.height )
122 {
123 int x1 = wxMin(x, rect.x);
124 int y1 = wxMin(y, rect.y);
125 int y2 = wxMax(y + height, rect.height + rect.y);
126 int x2 = wxMax(x + width, rect.width + rect.x);
127
128 x = x1;
129 y = y1;
130 width = x2 - x1;
131 height = y2 - y1;
132 }
133 //else: we're not empty and rect is empty
134
135 return *this;
136 }
137
138 wxRect& wxRect::Inflate(wxCoord dx, wxCoord dy)
139 {
140 if (-2*dx>width)
141 {
142 // Don't allow deflate to eat more width than we have,
143 // a well-defined rectangle cannot have negative width.
144 x+=width/2;
145 width=0;
146 }
147 else
148 {
149 // The inflate is valid.
150 x-=dx;
151 width+=2*dx;
152 }
153
154 if (-2*dy>height)
155 {
156 // Don't allow deflate to eat more height than we have,
157 // a well-defined rectangle cannot have negative height.
158 y+=height/2;
159 height=0;
160 }
161 else
162 {
163 // The inflate is valid.
164 y-=dy;
165 height+=2*dy;
166 }
167
168 return *this;
169 }
170
171 bool wxRect::Contains(int cx, int cy) const
172 {
173 return ( (cx >= x) && (cy >= y)
174 && ((cy - y) < height)
175 && ((cx - x) < width)
176 );
177 }
178
179 bool wxRect::Contains(const wxRect& rect) const
180 {
181 return Contains(rect.GetTopLeft()) && Contains(rect.GetBottomRight());
182 }
183
184 wxRect& wxRect::Intersect(const wxRect& rect)
185 {
186 int x2 = GetRight(),
187 y2 = GetBottom();
188
189 if ( x < rect.x )
190 x = rect.x;
191 if ( y < rect.y )
192 y = rect.y;
193 if ( x2 > rect.GetRight() )
194 x2 = rect.GetRight();
195 if ( y2 > rect.GetBottom() )
196 y2 = rect.GetBottom();
197
198 width = x2 - x + 1;
199 height = y2 - y + 1;
200
201 if ( width <= 0 || height <= 0 )
202 {
203 width =
204 height = 0;
205 }
206
207 return *this;
208 }
209
210 bool wxRect::Intersects(const wxRect& rect) const
211 {
212 wxRect r = Intersect(rect);
213
214 // if there is no intersection, both width and height are 0
215 return r.width != 0;
216 }
217
218 wxRect& wxRect::operator+=(const wxRect& rect)
219 {
220 *this = *this + rect;
221 return *this;
222 }
223
224
225 wxRect& wxRect::operator*=(const wxRect& rect)
226 {
227 *this = *this * rect;
228 return *this;
229 }
230
231
232 wxRect operator+(const wxRect& r1, const wxRect& r2)
233 {
234 int x1 = wxMin(r1.x, r2.x);
235 int y1 = wxMin(r1.y, r2.y);
236 int y2 = wxMax(r1.y+r1.height, r2.height+r2.y);
237 int x2 = wxMax(r1.x+r1.width, r2.width+r2.x);
238 return wxRect(x1, y1, x2-x1, y2-y1);
239 }
240
241 wxRect operator*(const wxRect& r1, const wxRect& r2)
242 {
243 int x1 = wxMax(r1.x, r2.x);
244 int y1 = wxMax(r1.y, r2.y);
245 int y2 = wxMin(r1.y+r1.height, r2.height+r2.y);
246 int x2 = wxMin(r1.x+r1.width, r2.width+r2.x);
247 return wxRect(x1, y1, x2-x1, y2-y1);
248 }
249
250 // ============================================================================
251 // wxColourDatabase
252 // ============================================================================
253
254 // ----------------------------------------------------------------------------
255 // wxColourDatabase ctor/dtor
256 // ----------------------------------------------------------------------------
257
258 wxColourDatabase::wxColourDatabase ()
259 {
260 // will be created on demand in Initialize()
261 m_map = NULL;
262 }
263
264 wxColourDatabase::~wxColourDatabase ()
265 {
266 if ( m_map )
267 {
268 WX_CLEAR_HASH_MAP(wxStringToColourHashMap, *m_map);
269
270 delete m_map;
271 }
272
273 #ifdef __WXPM__
274 delete [] m_palTable;
275 #endif
276 }
277
278 // Colour database stuff
279 void wxColourDatabase::Initialize()
280 {
281 if ( m_map )
282 {
283 // already initialized
284 return;
285 }
286
287 m_map = new wxStringToColourHashMap;
288
289 static const struct wxColourDesc
290 {
291 const wxChar *name;
292 unsigned char r,g,b;
293 }
294 wxColourTable[] =
295 {
296 {wxT("AQUAMARINE"),112, 219, 147},
297 {wxT("BLACK"),0, 0, 0},
298 {wxT("BLUE"), 0, 0, 255},
299 {wxT("BLUE VIOLET"), 159, 95, 159},
300 {wxT("BROWN"), 165, 42, 42},
301 {wxT("CADET BLUE"), 95, 159, 159},
302 {wxT("CORAL"), 255, 127, 0},
303 {wxT("CORNFLOWER BLUE"), 66, 66, 111},
304 {wxT("CYAN"), 0, 255, 255},
305 {wxT("DARK GREY"), 47, 47, 47}, // ?
306
307 {wxT("DARK GREEN"), 47, 79, 47},
308 {wxT("DARK OLIVE GREEN"), 79, 79, 47},
309 {wxT("DARK ORCHID"), 153, 50, 204},
310 {wxT("DARK SLATE BLUE"), 107, 35, 142},
311 {wxT("DARK SLATE GREY"), 47, 79, 79},
312 {wxT("DARK TURQUOISE"), 112, 147, 219},
313 {wxT("DIM GREY"), 84, 84, 84},
314 {wxT("FIREBRICK"), 142, 35, 35},
315 {wxT("FOREST GREEN"), 35, 142, 35},
316 {wxT("GOLD"), 204, 127, 50},
317 {wxT("GOLDENROD"), 219, 219, 112},
318 {wxT("GREY"), 128, 128, 128},
319 {wxT("GREEN"), 0, 255, 0},
320 {wxT("GREEN YELLOW"), 147, 219, 112},
321 {wxT("INDIAN RED"), 79, 47, 47},
322 {wxT("KHAKI"), 159, 159, 95},
323 {wxT("LIGHT BLUE"), 191, 216, 216},
324 {wxT("LIGHT GREY"), 192, 192, 192},
325 {wxT("LIGHT STEEL BLUE"), 143, 143, 188},
326 {wxT("LIME GREEN"), 50, 204, 50},
327 {wxT("LIGHT MAGENTA"), 255, 0, 255},
328 {wxT("MAGENTA"), 255, 0, 255},
329 {wxT("MAROON"), 142, 35, 107},
330 {wxT("MEDIUM AQUAMARINE"), 50, 204, 153},
331 {wxT("MEDIUM GREY"), 100, 100, 100},
332 {wxT("MEDIUM BLUE"), 50, 50, 204},
333 {wxT("MEDIUM FOREST GREEN"), 107, 142, 35},
334 {wxT("MEDIUM GOLDENROD"), 234, 234, 173},
335 {wxT("MEDIUM ORCHID"), 147, 112, 219},
336 {wxT("MEDIUM SEA GREEN"), 66, 111, 66},
337 {wxT("MEDIUM SLATE BLUE"), 127, 0, 255},
338 {wxT("MEDIUM SPRING GREEN"), 127, 255, 0},
339 {wxT("MEDIUM TURQUOISE"), 112, 219, 219},
340 {wxT("MEDIUM VIOLET RED"), 219, 112, 147},
341 {wxT("MIDNIGHT BLUE"), 47, 47, 79},
342 {wxT("NAVY"), 35, 35, 142},
343 {wxT("ORANGE"), 204, 50, 50},
344 {wxT("ORANGE RED"), 255, 0, 127},
345 {wxT("ORCHID"), 219, 112, 219},
346 {wxT("PALE GREEN"), 143, 188, 143},
347 {wxT("PINK"), 255, 192, 203},
348 {wxT("PLUM"), 234, 173, 234},
349 {wxT("PURPLE"), 176, 0, 255},
350 {wxT("RED"), 255, 0, 0},
351 {wxT("SALMON"), 111, 66, 66},
352 {wxT("SEA GREEN"), 35, 142, 107},
353 {wxT("SIENNA"), 142, 107, 35},
354 {wxT("SKY BLUE"), 50, 153, 204},
355 {wxT("SLATE BLUE"), 0, 127, 255},
356 {wxT("SPRING GREEN"), 0, 255, 127},
357 {wxT("STEEL BLUE"), 35, 107, 142},
358 {wxT("TAN"), 219, 147, 112},
359 {wxT("THISTLE"), 216, 191, 216},
360 {wxT("TURQUOISE"), 173, 234, 234},
361 {wxT("VIOLET"), 79, 47, 79},
362 {wxT("VIOLET RED"), 204, 50, 153},
363 {wxT("WHEAT"), 216, 216, 191},
364 {wxT("WHITE"), 255, 255, 255},
365 {wxT("YELLOW"), 255, 255, 0},
366 {wxT("YELLOW GREEN"), 153, 204, 50}
367 };
368
369 size_t n;
370
371 for ( n = 0; n < WXSIZEOF(wxColourTable); n++ )
372 {
373 const wxColourDesc& cc = wxColourTable[n];
374 (*m_map)[cc.name] = new wxColour(cc.r, cc.g, cc.b);
375 }
376
377 #ifdef __WXPM__
378 m_palTable = new long[n];
379 for ( n = 0; n < WXSIZEOF(wxColourTable); n++ )
380 {
381 const wxColourDesc& cc = wxColourTable[n];
382 m_palTable[n] = OS2RGB(cc.r,cc.g,cc.b);
383 }
384 m_nSize = n;
385 #endif
386 }
387
388 // ----------------------------------------------------------------------------
389 // wxColourDatabase operations
390 // ----------------------------------------------------------------------------
391
392 void wxColourDatabase::AddColour(const wxString& name, const wxColour& colour)
393 {
394 Initialize();
395
396 // canonicalize the colour names before using them as keys: they should be
397 // in upper case
398 wxString colName = name;
399 colName.MakeUpper();
400
401 // ... and we also allow both grey/gray
402 wxString colNameAlt = colName;
403 if ( !colNameAlt.Replace(_T("GRAY"), _T("GREY")) )
404 {
405 // but in this case it is not necessary so avoid extra search below
406 colNameAlt.clear();
407 }
408
409 wxStringToColourHashMap::iterator it = m_map->find(colName);
410 if ( it == m_map->end() && !colNameAlt.empty() )
411 it = m_map->find(colNameAlt);
412 if ( it != m_map->end() )
413 {
414 *(it->second) = colour;
415 }
416 else // new colour
417 {
418 (*m_map)[colName] = new wxColour(colour);
419 }
420 }
421
422 wxColour wxColourDatabase::Find(const wxString& colour) const
423 {
424 wxColourDatabase * const self = wxConstCast(this, wxColourDatabase);
425 self->Initialize();
426
427 // make the comparaison case insensitive and also match both grey and gray
428 wxString colName = colour;
429 colName.MakeUpper();
430 wxString colNameAlt = colName;
431 if ( !colNameAlt.Replace(_T("GRAY"), _T("GREY")) )
432 colNameAlt.clear();
433
434 wxStringToColourHashMap::iterator it = m_map->find(colName);
435 if ( it == m_map->end() && !colNameAlt.empty() )
436 it = m_map->find(colNameAlt);
437 if ( it != m_map->end() )
438 return *(it->second);
439
440 // we did not find any result in existing colours:
441 // we won't use wxString -> wxColour conversion because the
442 // wxColour::Set(const wxString &) function which does that conversion
443 // internally uses this function (wxColourDatabase::Find) and we want
444 // to avoid infinite recursion !
445 return wxNullColour;
446 }
447
448 wxString wxColourDatabase::FindName(const wxColour& colour) const
449 {
450 wxColourDatabase * const self = wxConstCast(this, wxColourDatabase);
451 self->Initialize();
452
453 typedef wxStringToColourHashMap::iterator iterator;
454
455 for ( iterator it = m_map->begin(), en = m_map->end(); it != en; ++it )
456 {
457 if ( *(it->second) == colour )
458 return it->first;
459 }
460
461 return wxEmptyString;
462 }
463
464 // ----------------------------------------------------------------------------
465 // deprecated wxColourDatabase methods
466 // ----------------------------------------------------------------------------
467
468 #if WXWIN_COMPATIBILITY_2_6
469 wxColour *wxColourDatabase::FindColour(const wxString& name)
470 {
471 // This function is deprecated, use Find() instead.
472 // Formerly this function sometimes would return a deletable pointer and
473 // sometimes a non-deletable one (when returning a colour from the database).
474 // Trying to delete the latter anyway results in problems, so probably
475 // nobody ever freed the pointers. Currently it always returns a new
476 // instance, which means there will be memory leaks.
477 wxLogDebug(wxT("wxColourDataBase::FindColour():")
478 wxT(" Please use wxColourDataBase::Find() instead"));
479
480 // using a static variable here is not the most elegant solution but unless
481 // we want to make wxStringToColourHashMap public (i.e. move it to the
482 // header) so that we could have a member function returning
483 // wxStringToColourHashMap::iterator, there is really no good way to do it
484 // otherwise
485 //
486 // and knowing that this function is going to disappear in the next release
487 // anyhow I don't want to waste time on this
488
489 static wxColour s_col;
490
491 s_col = Find(name);
492 if ( !s_col.Ok() )
493 return NULL;
494
495 return new wxColour(s_col);
496 }
497 #endif // WXWIN_COMPATIBILITY_2_6
498
499 // ============================================================================
500 // stock objects
501 // ============================================================================
502
503 static wxStockGDI gs_wxStockGDI_instance;
504 wxStockGDI* wxStockGDI::ms_instance = &gs_wxStockGDI_instance;
505 wxObject* wxStockGDI::ms_stockObject[ITEMCOUNT];
506
507 wxStockGDI::wxStockGDI()
508 {
509 }
510
511 wxStockGDI::~wxStockGDI()
512 {
513 }
514
515 void wxStockGDI::DeleteAll()
516 {
517 for (unsigned i = 0; i < ITEMCOUNT; i++)
518 {
519 delete ms_stockObject[i];
520 ms_stockObject[i] = NULL;
521 }
522 }
523
524 const wxBrush* wxStockGDI::GetBrush(Item item)
525 {
526 wxBrush* brush = wx_static_cast(wxBrush*, ms_stockObject[item]);
527 if (brush == NULL)
528 {
529 switch (item)
530 {
531 case BRUSH_BLACK:
532 brush = new wxBrush(*GetColour(COLOUR_BLACK), wxSOLID);
533 break;
534 case BRUSH_BLUE:
535 brush = new wxBrush(*GetColour(COLOUR_BLUE), wxSOLID);
536 break;
537 case BRUSH_CYAN:
538 brush = new wxBrush(*GetColour(COLOUR_CYAN), wxSOLID);
539 break;
540 case BRUSH_GREEN:
541 brush = new wxBrush(*GetColour(COLOUR_GREEN), wxSOLID);
542 break;
543 case BRUSH_GREY:
544 brush = new wxBrush(wxColour(wxT("GREY")), wxSOLID);
545 break;
546 case BRUSH_LIGHTGREY:
547 brush = new wxBrush(*GetColour(COLOUR_LIGHTGREY), wxSOLID);
548 break;
549 case BRUSH_MEDIUMGREY:
550 brush = new wxBrush(wxColour(wxT("MEDIUM GREY")), wxSOLID);
551 break;
552 case BRUSH_RED:
553 brush = new wxBrush(*GetColour(COLOUR_RED), wxSOLID);
554 break;
555 case BRUSH_TRANSPARENT:
556 brush = new wxBrush(*GetColour(COLOUR_BLACK), wxTRANSPARENT);
557 break;
558 case BRUSH_WHITE:
559 brush = new wxBrush(*GetColour(COLOUR_WHITE), wxSOLID);
560 break;
561 default:
562 wxFAIL;
563 }
564 ms_stockObject[item] = brush;
565 }
566 return brush;
567 }
568
569 const wxColour* wxStockGDI::GetColour(Item item)
570 {
571 wxColour* colour = wx_static_cast(wxColour*, ms_stockObject[item]);
572 if (colour == NULL)
573 {
574 switch (item)
575 {
576 case COLOUR_BLACK:
577 colour = new wxColour(0, 0, 0);
578 break;
579 case COLOUR_BLUE:
580 colour = new wxColour(0, 0, 255);
581 break;
582 case COLOUR_CYAN:
583 colour = new wxColour(wxT("CYAN"));
584 break;
585 case COLOUR_GREEN:
586 colour = new wxColour(0, 255, 0);
587 break;
588 case COLOUR_LIGHTGREY:
589 colour = new wxColour(wxT("LIGHT GREY"));
590 break;
591 case COLOUR_RED:
592 colour = new wxColour(255, 0, 0);
593 break;
594 case COLOUR_WHITE:
595 colour = new wxColour(255, 255, 255);
596 break;
597 default:
598 wxFAIL;
599 }
600 ms_stockObject[item] = colour;
601 }
602 return colour;
603 }
604
605 const wxCursor* wxStockGDI::GetCursor(Item item)
606 {
607 wxCursor* cursor = wx_static_cast(wxCursor*, ms_stockObject[item]);
608 if (cursor == NULL)
609 {
610 switch (item)
611 {
612 case CURSOR_CROSS:
613 cursor = new wxCursor(wxCURSOR_CROSS);
614 break;
615 case CURSOR_HOURGLASS:
616 cursor = new wxCursor(wxCURSOR_WAIT);
617 break;
618 case CURSOR_STANDARD:
619 cursor = new wxCursor(wxCURSOR_ARROW);
620 break;
621 default:
622 wxFAIL;
623 }
624 ms_stockObject[item] = cursor;
625 }
626 return cursor;
627 }
628
629 const wxFont* wxStockGDI::GetFont(Item item)
630 {
631 wxFont* font = wx_static_cast(wxFont*, ms_stockObject[item]);
632 if (font == NULL)
633 {
634 switch (item)
635 {
636 case FONT_ITALIC:
637 font = new wxFont(GetFont(FONT_NORMAL)->GetPointSize(), wxROMAN, wxITALIC, wxNORMAL);
638 break;
639 case FONT_NORMAL:
640 font = new wxFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
641 break;
642 case FONT_SMALL:
643 font = new wxFont(GetFont(FONT_NORMAL)->GetPointSize() - 2, wxSWISS, wxNORMAL, wxNORMAL);
644 break;
645 case FONT_SWISS:
646 font = new wxFont(GetFont(FONT_NORMAL)->GetPointSize(), wxSWISS, wxNORMAL, wxNORMAL);
647 break;
648 default:
649 wxFAIL;
650 }
651 ms_stockObject[item] = font;
652 }
653 return font;
654 }
655
656 const wxPen* wxStockGDI::GetPen(Item item)
657 {
658 wxPen* pen = wx_static_cast(wxPen*, ms_stockObject[item]);
659 if (pen == NULL)
660 {
661 switch (item)
662 {
663 case PEN_BLACK:
664 pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxSOLID);
665 break;
666 case PEN_BLACKDASHED:
667 pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxSHORT_DASH);
668 break;
669 case PEN_CYAN:
670 pen = new wxPen(*GetColour(COLOUR_CYAN), 1, wxSOLID);
671 break;
672 case PEN_GREEN:
673 pen = new wxPen(*GetColour(COLOUR_GREEN), 1, wxSOLID);
674 break;
675 case PEN_GREY:
676 pen = new wxPen(wxColour(wxT("GREY")), 1, wxSOLID);
677 break;
678 case PEN_LIGHTGREY:
679 pen = new wxPen(*GetColour(COLOUR_LIGHTGREY), 1, wxSOLID);
680 break;
681 case PEN_MEDIUMGREY:
682 pen = new wxPen(wxColour(wxT("MEDIUM GREY")), 1, wxSOLID);
683 break;
684 case PEN_RED:
685 pen = new wxPen(*GetColour(COLOUR_RED), 1, wxSOLID);
686 break;
687 case PEN_TRANSPARENT:
688 pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxTRANSPARENT);
689 break;
690 case PEN_WHITE:
691 pen = new wxPen(*GetColour(COLOUR_WHITE), 1, wxSOLID);
692 break;
693 default:
694 wxFAIL;
695 }
696 ms_stockObject[item] = pen;
697 }
698 return pen;
699 }
700
701 void wxInitializeStockLists()
702 {
703 wxTheColourDatabase = new wxColourDatabase;
704
705 wxTheBrushList = new wxBrushList;
706 wxThePenList = new wxPenList;
707 wxTheFontList = new wxFontList;
708 }
709
710 void wxDeleteStockLists()
711 {
712 wxDELETE(wxTheBrushList);
713 wxDELETE(wxThePenList);
714 wxDELETE(wxTheFontList);
715 }
716
717 // ============================================================================
718 // wxTheXXXList stuff (semi-obsolete)
719 // ============================================================================
720
721 wxGDIObjListBase::wxGDIObjListBase()
722 {
723 }
724
725 wxGDIObjListBase::~wxGDIObjListBase()
726 {
727 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
728 {
729 delete wx_static_cast(wxObject*, node->GetData());
730 }
731 }
732
733 wxPen *wxPenList::FindOrCreatePen (const wxColour& colour, int width, int style)
734 {
735 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
736 {
737 wxPen *each_pen = (wxPen *) node->GetData ();
738 if (
739 each_pen->GetWidth () == width &&
740 each_pen->GetStyle () == style &&
741 each_pen->GetColour ().Red () == colour.Red () &&
742 each_pen->GetColour ().Green () == colour.Green () &&
743 each_pen->GetColour ().Blue () == colour.Blue ())
744 return each_pen;
745 }
746
747 wxPen* pen = NULL;
748 wxPen penTmp(colour, width, style);
749 if (penTmp.Ok())
750 {
751 pen = new wxPen(penTmp);
752 list.Append(pen);
753 }
754
755 return pen;
756 }
757
758 wxBrush *wxBrushList::FindOrCreateBrush (const wxColour& colour, int style)
759 {
760 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
761 {
762 wxBrush *each_brush = (wxBrush *) node->GetData ();
763 if (
764 each_brush->GetStyle () == style &&
765 each_brush->GetColour ().Red () == colour.Red () &&
766 each_brush->GetColour ().Green () == colour.Green () &&
767 each_brush->GetColour ().Blue () == colour.Blue ())
768 return each_brush;
769 }
770
771 wxBrush* brush = NULL;
772 wxBrush brushTmp(colour, style);
773 if (brushTmp.Ok())
774 {
775 brush = new wxBrush(brushTmp);
776 list.Append(brush);
777 }
778
779 return brush;
780 }
781
782 wxFont *wxFontList::FindOrCreateFont(int pointSize,
783 int family,
784 int style,
785 int weight,
786 bool underline,
787 const wxString& facename,
788 wxFontEncoding encoding)
789 {
790 wxFont *font;
791 wxList::compatibility_iterator node;
792 for (node = list.GetFirst(); node; node = node->GetNext())
793 {
794 font = (wxFont *)node->GetData();
795 if (
796 font->GetPointSize () == pointSize &&
797 font->GetStyle () == style &&
798 font->GetWeight () == weight &&
799 font->GetUnderlined () == underline )
800 {
801 int fontFamily = font->GetFamily();
802
803 #if defined(__WXGTK__)
804 // under GTK the default family is wxSWISS, so looking for a font
805 // with wxDEFAULT family should return a wxSWISS one instead of
806 // creating a new one
807 bool same = (fontFamily == family) ||
808 (fontFamily == wxSWISS && family == wxDEFAULT);
809 #else // !GTK
810 // VZ: but why elsewhere do we require an exact match? mystery...
811 bool same = fontFamily == family;
812 #endif // GTK/!GTK
813
814 // empty facename matches anything at all: this is bad because
815 // depending on which fonts are already created, we might get back
816 // a different font if we create it with empty facename, but it is
817 // still better than never matching anything in the cache at all
818 // in this case
819 if ( same && !facename.empty() )
820 {
821 const wxString& fontFace = font->GetFaceName();
822
823 // empty facename matches everything
824 same = !fontFace || fontFace == facename;
825 }
826
827 if ( same && (encoding != wxFONTENCODING_DEFAULT) )
828 {
829 // have to match the encoding too
830 same = font->GetEncoding() == encoding;
831 }
832
833 if ( same )
834 {
835 return font;
836 }
837 }
838 }
839
840 // font not found, create the new one
841 font = NULL;
842 wxFont fontTmp(pointSize, family, style, weight, underline, facename, encoding);
843 if (fontTmp.Ok())
844 {
845 font = new wxFont(fontTmp);
846 list.Append(font);
847 }
848
849 return font;
850 }
851
852 #if WXWIN_COMPATIBILITY_2_6
853 void wxBrushList::AddBrush(wxBrush*) { }
854 void wxBrushList::RemoveBrush(wxBrush*) { }
855 void wxFontList::AddFont(wxFont*) { }
856 void wxFontList::RemoveFont(wxFont*) { }
857 void wxPenList::AddPen(wxPen*) { }
858 void wxPenList::RemovePen(wxPen*) { }
859 #endif
860
861 wxSize wxGetDisplaySize()
862 {
863 int x, y;
864 wxDisplaySize(& x, & y);
865 return wxSize(x, y);
866 }
867
868 wxRect wxGetClientDisplayRect()
869 {
870 int x, y, width, height;
871 wxClientDisplayRect(&x, &y, &width, &height); // call plat-specific version
872 return wxRect(x, y, width, height);
873 }
874
875 wxSize wxGetDisplaySizeMM()
876 {
877 int x, y;
878 wxDisplaySizeMM(& x, & y);
879 return wxSize(x, y);
880 }
881
882 wxResourceCache::~wxResourceCache ()
883 {
884 wxList::compatibility_iterator node = GetFirst ();
885 while (node) {
886 wxObject *item = (wxObject *)node->GetData();
887 delete item;
888
889 node = node->GetNext ();
890 }
891 }