]> git.saurik.com Git - wxWidgets.git/blob - src/generic/colrdlgg.cpp
fixing reentrancy which happened in tests, bringing client coordinates origins in...
[wxWidgets.git] / src / generic / colrdlgg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/colrdlgg.cpp
3 // Purpose: Choice dialogs
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
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 #if wxUSE_COLOURDLG
20
21 #ifndef WX_PRECOMP
22 #include "wx/utils.h"
23 #include "wx/intl.h"
24 #include "wx/dialog.h"
25 #include "wx/listbox.h"
26 #include "wx/button.h"
27 #include "wx/stattext.h"
28 #include "wx/layout.h"
29 #include "wx/dcclient.h"
30 #include "wx/sizer.h"
31 #include "wx/slider.h"
32 #endif
33
34 #if wxUSE_STATLINE
35 #include "wx/statline.h"
36 #endif
37
38 #include "wx/colourdata.h"
39 #include "wx/generic/colrdlgg.h"
40
41 IMPLEMENT_DYNAMIC_CLASS(wxGenericColourDialog, wxDialog)
42
43 BEGIN_EVENT_TABLE(wxGenericColourDialog, wxDialog)
44 EVT_BUTTON(wxID_ADD_CUSTOM, wxGenericColourDialog::OnAddCustom)
45 #if wxUSE_SLIDER
46 EVT_SLIDER(wxID_RED_SLIDER, wxGenericColourDialog::OnRedSlider)
47 EVT_SLIDER(wxID_GREEN_SLIDER, wxGenericColourDialog::OnGreenSlider)
48 EVT_SLIDER(wxID_BLUE_SLIDER, wxGenericColourDialog::OnBlueSlider)
49 #endif
50 EVT_PAINT(wxGenericColourDialog::OnPaint)
51 EVT_MOUSE_EVENTS(wxGenericColourDialog::OnMouseEvent)
52 EVT_CLOSE(wxGenericColourDialog::OnCloseWindow)
53 END_EVENT_TABLE()
54
55
56 /*
57 * Generic wxColourDialog
58 */
59
60 // don't change the number of elements (48) in this array, the code below is
61 // hardcoded to use it
62 static const wxChar *const wxColourDialogNames[] =
63 {
64 wxT("ORANGE"),
65 wxT("GOLDENROD"),
66 wxT("WHEAT"),
67 wxT("SPRING GREEN"),
68 wxT("SKY BLUE"),
69 wxT("SLATE BLUE"),
70 wxT("MEDIUM VIOLET RED"),
71 wxT("PURPLE"),
72
73 wxT("RED"),
74 wxT("YELLOW"),
75 wxT("MEDIUM SPRING GREEN"),
76 wxT("PALE GREEN"),
77 wxT("CYAN"),
78 wxT("LIGHT STEEL BLUE"),
79 wxT("ORCHID"),
80 wxT("LIGHT MAGENTA"),
81
82 wxT("BROWN"),
83 wxT("YELLOW"),
84 wxT("GREEN"),
85 wxT("CADET BLUE"),
86 wxT("MEDIUM BLUE"),
87 wxT("MAGENTA"),
88 wxT("MAROON"),
89 wxT("ORANGE RED"),
90
91 wxT("FIREBRICK"),
92 wxT("CORAL"),
93 wxT("FOREST GREEN"),
94 wxT("AQUAMARINE"),
95 wxT("BLUE"),
96 wxT("NAVY"),
97 wxT("THISTLE"),
98 wxT("MEDIUM VIOLET RED"),
99
100 wxT("INDIAN RED"),
101 wxT("GOLD"),
102 wxT("MEDIUM SEA GREEN"),
103 wxT("MEDIUM BLUE"),
104 wxT("MIDNIGHT BLUE"),
105 wxT("GREY"),
106 wxT("PURPLE"),
107 wxT("KHAKI"),
108
109 wxT("BLACK"),
110 wxT("MEDIUM FOREST GREEN"),
111 wxT("KHAKI"),
112 wxT("DARK GREY"),
113 wxT("SEA GREEN"),
114 wxT("LIGHT GREY"),
115 wxT("MEDIUM SLATE BLUE"),
116 wxT("WHITE")
117 };
118
119 wxGenericColourDialog::wxGenericColourDialog()
120 {
121 m_whichKind = 1;
122 m_colourSelection = -1;
123 }
124
125 wxGenericColourDialog::wxGenericColourDialog(wxWindow *parent,
126 wxColourData *data)
127 {
128 m_whichKind = 1;
129 m_colourSelection = -1;
130 Create(parent, data);
131 }
132
133 wxGenericColourDialog::~wxGenericColourDialog()
134 {
135 }
136
137 void wxGenericColourDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
138 {
139 EndModal(wxID_CANCEL);
140 }
141
142 bool wxGenericColourDialog::Create(wxWindow *parent, wxColourData *data)
143 {
144 if ( !wxDialog::Create(GetParentForModalDialog(parent, 0), wxID_ANY,
145 _("Choose colour"),
146 wxPoint(0, 0), wxSize(900, 900)) )
147 return false;
148
149 if (data)
150 m_colourData = *data;
151
152 InitializeColours();
153 CalculateMeasurements();
154 CreateWidgets();
155
156 return true;
157 }
158
159 int wxGenericColourDialog::ShowModal()
160 {
161 return wxDialog::ShowModal();
162 }
163
164
165 // Internal functions
166 void wxGenericColourDialog::OnMouseEvent(wxMouseEvent& event)
167 {
168 if (event.ButtonDown(1))
169 {
170 int x = (int)event.GetX();
171 int y = (int)event.GetY();
172
173 #ifdef __WXPM__
174 // Handle OS/2's reverse coordinate system and account for the dialog title
175 int nClientHeight;
176
177 GetClientSize(NULL, &nClientHeight);
178 y = (nClientHeight - y) + 20;
179 #endif
180 if ((x >= m_standardColoursRect.x && x <= (m_standardColoursRect.x + m_standardColoursRect.width)) &&
181 (y >= m_standardColoursRect.y && y <= (m_standardColoursRect.y + m_standardColoursRect.height)))
182 {
183 int selX = (int)(x - m_standardColoursRect.x)/(m_smallRectangleSize.x + m_gridSpacing);
184 int selY = (int)(y - m_standardColoursRect.y)/(m_smallRectangleSize.y + m_gridSpacing);
185 int ptr = (int)(selX + selY*8);
186 OnBasicColourClick(ptr);
187 }
188 else if ((x >= m_customColoursRect.x && x <= (m_customColoursRect.x + m_customColoursRect.width)) &&
189 (y >= m_customColoursRect.y && y <= (m_customColoursRect.y + m_customColoursRect.height)))
190 {
191 int selX = (int)(x - m_customColoursRect.x)/(m_smallRectangleSize.x + m_gridSpacing);
192 int selY = (int)(y - m_customColoursRect.y)/(m_smallRectangleSize.y + m_gridSpacing);
193 int ptr = (int)(selX + selY*8);
194 OnCustomColourClick(ptr);
195 }
196 else
197 event.Skip();
198 }
199 else
200 event.Skip();
201 }
202
203 void wxGenericColourDialog::OnPaint(wxPaintEvent& WXUNUSED(event))
204 {
205 wxPaintDC dc(this);
206
207 PaintBasicColours(dc);
208 PaintCustomColours(dc);
209 PaintCustomColour(dc);
210 PaintHighlight(dc, true);
211 }
212
213 void wxGenericColourDialog::CalculateMeasurements()
214 {
215 m_smallRectangleSize.x = 18;
216 m_smallRectangleSize.y = 14;
217 m_customRectangleSize.x = 40;
218 m_customRectangleSize.y = 40;
219
220 m_gridSpacing = 6;
221 m_sectionSpacing = 15;
222
223 m_standardColoursRect.x = 10;
224 #ifdef __WXPM__
225 m_standardColoursRect.y = 15 + 20; /* OS/2 needs to account for dialog titlebar */
226 #else
227 m_standardColoursRect.y = 15;
228 #endif
229 m_standardColoursRect.width = (8*m_smallRectangleSize.x) + (7*m_gridSpacing);
230 m_standardColoursRect.height = (6*m_smallRectangleSize.y) + (5*m_gridSpacing);
231
232 m_customColoursRect.x = m_standardColoursRect.x;
233 m_customColoursRect.y = m_standardColoursRect.y + m_standardColoursRect.height + 20;
234 m_customColoursRect.width = (8*m_smallRectangleSize.x) + (7*m_gridSpacing);
235 m_customColoursRect.height = (2*m_smallRectangleSize.y) + (1*m_gridSpacing);
236
237 m_singleCustomColourRect.x = m_customColoursRect.width + m_customColoursRect.x + m_sectionSpacing;
238 m_singleCustomColourRect.y = 80;
239 m_singleCustomColourRect.width = m_customRectangleSize.x;
240 m_singleCustomColourRect.height = m_customRectangleSize.y;
241
242 m_okButtonX = 10;
243 m_customButtonX = m_singleCustomColourRect.x ;
244 m_buttonY = m_customColoursRect.y + m_customColoursRect.height + 10;
245 }
246
247 void wxGenericColourDialog::CreateWidgets()
248 {
249 wxBeginBusyCursor();
250
251 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
252
253 const int sliderHeight = 160;
254
255 // first sliders
256 #if wxUSE_SLIDER
257 const int sliderX = m_singleCustomColourRect.x + m_singleCustomColourRect.width + m_sectionSpacing;
258
259 m_redSlider = new wxSlider(this, wxID_RED_SLIDER, m_colourData.m_dataColour.Red(), 0, 255,
260 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxSL_VERTICAL|wxSL_LABELS|wxSL_INVERSE);
261 m_greenSlider = new wxSlider(this, wxID_GREEN_SLIDER, m_colourData.m_dataColour.Green(), 0, 255,
262 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxSL_VERTICAL|wxSL_LABELS|wxSL_INVERSE);
263 m_blueSlider = new wxSlider(this, wxID_BLUE_SLIDER, m_colourData.m_dataColour.Blue(), 0, 255,
264 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxSL_VERTICAL|wxSL_LABELS|wxSL_INVERSE);
265
266 wxBoxSizer *sliderSizer = new wxBoxSizer( wxHORIZONTAL );
267
268 sliderSizer->Add(sliderX, sliderHeight );
269
270 wxSizerFlags flagsRight;
271 flagsRight.Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL).DoubleBorder();
272
273 sliderSizer->Add(m_redSlider, flagsRight);
274 sliderSizer->Add(m_greenSlider,flagsRight);
275 sliderSizer->Add(m_blueSlider,flagsRight);
276
277 topSizer->Add(sliderSizer, wxSizerFlags().Centre().DoubleBorder());
278 #else
279 topSizer->Add(1, sliderHeight, wxSizerFlags(1).Centre().TripleBorder());
280 #endif // wxUSE_SLIDER
281
282 // then the custom button
283 topSizer->Add(new wxButton(this, wxID_ADD_CUSTOM,
284 _("Add to custom colours") ),
285 wxSizerFlags().DoubleHorzBorder());
286
287 // then the standard buttons
288 wxSizer *buttonsizer = CreateSeparatedButtonSizer(wxOK | wxCANCEL);
289 if ( buttonsizer )
290 {
291 topSizer->Add(buttonsizer, wxSizerFlags().Expand().DoubleBorder());
292 }
293
294 SetAutoLayout( true );
295 SetSizer( topSizer );
296
297 topSizer->SetSizeHints( this );
298 topSizer->Fit( this );
299
300 Centre( wxBOTH );
301
302 wxEndBusyCursor();
303 }
304
305 void wxGenericColourDialog::InitializeColours(void)
306 {
307 size_t i;
308
309 for (i = 0; i < WXSIZEOF(wxColourDialogNames); i++)
310 {
311 wxColour col = wxTheColourDatabase->Find(wxColourDialogNames[i]);
312 if (col.IsOk())
313 m_standardColours[i].Set(col.Red(), col.Green(), col.Blue());
314 else
315 m_standardColours[i].Set(0, 0, 0);
316 }
317
318 for (i = 0; i < WXSIZEOF(m_customColours); i++)
319 {
320 wxColour c = m_colourData.GetCustomColour(i);
321 if (c.IsOk())
322 m_customColours[i] = m_colourData.GetCustomColour(i);
323 else
324 m_customColours[i] = wxColour(255, 255, 255);
325 }
326
327 wxColour curr = m_colourData.GetColour();
328 if ( curr.IsOk() )
329 {
330 bool m_initColourFound = false;
331
332 for (i = 0; i < WXSIZEOF(wxColourDialogNames); i++)
333 {
334 if ( m_standardColours[i] == curr && !m_initColourFound )
335 {
336 m_whichKind = 1;
337 m_colourSelection = i;
338 m_initColourFound = true;
339 break;
340 }
341 }
342 if ( !m_initColourFound )
343 {
344 for ( i = 0; i < WXSIZEOF(m_customColours); i++ )
345 {
346 if ( m_customColours[i] == curr )
347 {
348 m_whichKind = 2;
349 m_colourSelection = i;
350 break;
351 }
352 }
353 }
354 m_colourData.m_dataColour.Set( curr.Red(), curr.Green(), curr.Blue() );
355 }
356 else
357 {
358 m_whichKind = 1;
359 m_colourSelection = 0;
360 m_colourData.m_dataColour.Set( 0, 0, 0 );
361 }
362 }
363
364 void wxGenericColourDialog::PaintBasicColours(wxDC& dc)
365 {
366 int i;
367 for (i = 0; i < 6; i++)
368 {
369 int j;
370 for (j = 0; j < 8; j++)
371 {
372 int ptr = i*8 + j;
373
374 int x = (j*(m_smallRectangleSize.x+m_gridSpacing) + m_standardColoursRect.x);
375 int y = (i*(m_smallRectangleSize.y+m_gridSpacing) + m_standardColoursRect.y);
376
377 dc.SetPen(*wxBLACK_PEN);
378 wxBrush brush(m_standardColours[ptr]);
379 dc.SetBrush(brush);
380
381 dc.DrawRectangle( x, y, m_smallRectangleSize.x, m_smallRectangleSize.y);
382 }
383 }
384 }
385
386 void wxGenericColourDialog::PaintCustomColours(wxDC& dc)
387 {
388 int i;
389 for (i = 0; i < 2; i++)
390 {
391 int j;
392 for (j = 0; j < 8; j++)
393 {
394 int ptr = i*8 + j;
395
396 int x = (j*(m_smallRectangleSize.x+m_gridSpacing)) + m_customColoursRect.x;
397 int y = (i*(m_smallRectangleSize.y+m_gridSpacing)) + m_customColoursRect.y;
398
399 dc.SetPen(*wxBLACK_PEN);
400
401 wxBrush brush(m_customColours[ptr]);
402 dc.SetBrush(brush);
403
404 dc.DrawRectangle( x, y, m_smallRectangleSize.x, m_smallRectangleSize.y);
405 }
406 }
407 }
408
409 void wxGenericColourDialog::PaintHighlight(wxDC& dc, bool draw)
410 {
411 if ( m_colourSelection < 0 )
412 return;
413
414 // Number of pixels bigger than the standard rectangle size
415 // for drawing a highlight
416 int deltaX = 2;
417 int deltaY = 2;
418
419 if (m_whichKind == 1)
420 {
421 // Standard colours
422 int y = (int)(m_colourSelection / 8);
423 int x = (int)(m_colourSelection - (y*8));
424
425 x = (x*(m_smallRectangleSize.x + m_gridSpacing) + m_standardColoursRect.x) - deltaX;
426 y = (y*(m_smallRectangleSize.y + m_gridSpacing) + m_standardColoursRect.y) - deltaY;
427
428 if (draw)
429 dc.SetPen(*wxBLACK_PEN);
430 else
431 dc.SetPen(*wxLIGHT_GREY_PEN);
432
433 dc.SetBrush(*wxTRANSPARENT_BRUSH);
434 dc.DrawRectangle( x, y, (m_smallRectangleSize.x + (2*deltaX)), (m_smallRectangleSize.y + (2*deltaY)));
435 }
436 else
437 {
438 // User-defined colours
439 int y = (int)(m_colourSelection / 8);
440 int x = (int)(m_colourSelection - (y*8));
441
442 x = (x*(m_smallRectangleSize.x + m_gridSpacing) + m_customColoursRect.x) - deltaX;
443 y = (y*(m_smallRectangleSize.y + m_gridSpacing) + m_customColoursRect.y) - deltaY;
444
445 if (draw)
446 dc.SetPen(*wxBLACK_PEN);
447 else
448 dc.SetPen(*wxLIGHT_GREY_PEN);
449
450 dc.SetBrush(*wxTRANSPARENT_BRUSH);
451 dc.DrawRectangle( x, y, (m_smallRectangleSize.x + (2*deltaX)), (m_smallRectangleSize.y + (2*deltaY)));
452 }
453 }
454
455 void wxGenericColourDialog::PaintCustomColour(wxDC& dc)
456 {
457 dc.SetPen(*wxBLACK_PEN);
458
459 wxBrush *brush = new wxBrush(m_colourData.m_dataColour);
460 dc.SetBrush(*brush);
461
462 dc.DrawRectangle( m_singleCustomColourRect.x, m_singleCustomColourRect.y,
463 m_customRectangleSize.x, m_customRectangleSize.y);
464
465 dc.SetBrush(wxNullBrush);
466 delete brush;
467 }
468
469 void wxGenericColourDialog::OnBasicColourClick(int which)
470 {
471 wxClientDC dc(this);
472
473 PaintHighlight(dc, false);
474 m_whichKind = 1;
475 m_colourSelection = which;
476
477 #if wxUSE_SLIDER
478 m_redSlider->SetValue( m_standardColours[m_colourSelection].Red() );
479 m_greenSlider->SetValue( m_standardColours[m_colourSelection].Green() );
480 m_blueSlider->SetValue( m_standardColours[m_colourSelection].Blue() );
481 #endif // wxUSE_SLIDER
482
483 m_colourData.m_dataColour.Set(m_standardColours[m_colourSelection].Red(),
484 m_standardColours[m_colourSelection].Green(),
485 m_standardColours[m_colourSelection].Blue());
486
487 PaintCustomColour(dc);
488 PaintHighlight(dc, true);
489 }
490
491 void wxGenericColourDialog::OnCustomColourClick(int which)
492 {
493 wxClientDC dc(this);
494 PaintHighlight(dc, false);
495 m_whichKind = 2;
496 m_colourSelection = which;
497
498 #if wxUSE_SLIDER
499 m_redSlider->SetValue( m_customColours[m_colourSelection].Red() );
500 m_greenSlider->SetValue( m_customColours[m_colourSelection].Green() );
501 m_blueSlider->SetValue( m_customColours[m_colourSelection].Blue() );
502 #endif // wxUSE_SLIDER
503
504 m_colourData.m_dataColour.Set(m_customColours[m_colourSelection].Red(),
505 m_customColours[m_colourSelection].Green(),
506 m_customColours[m_colourSelection].Blue());
507
508 PaintCustomColour(dc);
509 PaintHighlight(dc, true);
510 }
511
512 /*
513 void wxGenericColourDialog::OnOk(void)
514 {
515 Show(false);
516 }
517
518 void wxGenericColourDialog::OnCancel(void)
519 {
520 colourDialogCancelled = true;
521 Show(false);
522 }
523 */
524
525 void wxGenericColourDialog::OnAddCustom(wxCommandEvent& WXUNUSED(event))
526 {
527 wxClientDC dc(this);
528 if (m_whichKind != 2)
529 {
530 PaintHighlight(dc, false);
531 m_whichKind = 2;
532 m_colourSelection = 0;
533 PaintHighlight(dc, true);
534 }
535
536 m_customColours[m_colourSelection].Set(m_colourData.m_dataColour.Red(),
537 m_colourData.m_dataColour.Green(),
538 m_colourData.m_dataColour.Blue());
539
540 m_colourData.SetCustomColour(m_colourSelection, m_customColours[m_colourSelection]);
541
542 PaintCustomColours(dc);
543 }
544
545 #if wxUSE_SLIDER
546
547 void wxGenericColourDialog::OnRedSlider(wxCommandEvent& WXUNUSED(event))
548 {
549 if (!m_redSlider)
550 return;
551
552 wxClientDC dc(this);
553 m_colourData.m_dataColour.Set((unsigned char)m_redSlider->GetValue(), m_colourData.m_dataColour.Green(), m_colourData.m_dataColour.Blue());
554 PaintCustomColour(dc);
555 }
556
557 void wxGenericColourDialog::OnGreenSlider(wxCommandEvent& WXUNUSED(event))
558 {
559 if (!m_greenSlider)
560 return;
561
562 wxClientDC dc(this);
563 m_colourData.m_dataColour.Set(m_colourData.m_dataColour.Red(), (unsigned char)m_greenSlider->GetValue(), m_colourData.m_dataColour.Blue());
564 PaintCustomColour(dc);
565 }
566
567 void wxGenericColourDialog::OnBlueSlider(wxCommandEvent& WXUNUSED(event))
568 {
569 if (!m_blueSlider)
570 return;
571
572 wxClientDC dc(this);
573 m_colourData.m_dataColour.Set(m_colourData.m_dataColour.Red(), m_colourData.m_dataColour.Green(), (unsigned char)m_blueSlider->GetValue());
574 PaintCustomColour(dc);
575 }
576
577 #endif // wxUSE_SLIDER
578
579 #endif // wxUSE_COLOURDLG