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