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