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