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