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