1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/richtext/richtextsymboldlg.cpp
3 // Purpose:
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     10/5/2006 3:11:58 PM
7 // RCS-ID:      $Id: richtextsymboldlg.cpp 63745 2010-03-23 08:59:44Z JS $
8 // Copyright:   (c) Julian Smart
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14 
15 #ifdef __BORLANDC__
16     #pragma hdrstop
17 #endif
18 
19 #if wxUSE_RICHTEXT
20 
21 #include "wx/richtext/richtextsymboldlg.h"
22 
23 #ifndef WX_PRECOMP
24     #include "wx/sizer.h"
25     #include "wx/stattext.h"
26     #include "wx/combobox.h"
27     #include "wx/button.h"
28     #include "wx/settings.h"
29     #include "wx/icon.h"
30     #include "wx/listbox.h"
31 #endif
32 
33 #include "wx/dcbuffer.h"
34 
35 // Only for cached font name
36 #include "wx/richtext/richtextctrl.h"
37 
38 /* Microsoft Unicode subset numbering
39  */
40 
41 typedef enum
42 {
43   U_BASIC_LATIN = 0,
44   U_LATIN_1_SUPPLEMENT = 1,
45   U_LATIN_EXTENDED_A = 2,
46   U_LATIN_EXTENDED_B = 3,
47   U_IPA_EXTENSIONS = 4,
48   U_SPACING_MODIFIER_LETTERS = 5,
49   U_COMBINING_DIACRITICAL_MARKS = 6,
50   U_BASIC_GREEK = 7,
51   U_GREEK_SYMBOLS_AND_COPTIC = 8,
52   U_CYRILLIC = 9,
53   U_ARMENIAN = 10,
54   U_HEBREW_EXTENDED = 12,
55   U_BASIC_HEBREW = 11,
56   U_BASIC_ARABIC = 13,
57   U_ARABIC_EXTENDED = 14,
58   U_DEVANAGARI = 15,
59   U_BENGALI = 16,
60   U_GURMUKHI = 17,
61   U_GUJARATI = 18,
62   U_ORIYA = 19,
63   U_TAMIL = 20,
64   U_TELUGU = 21,
65   U_KANNADA = 22,
66   U_MALAYALAM = 23,
67   U_THAI = 24,
68   U_LAO = 25,
69   U_GEORGIAN_EXTENDED = 27,
70   U_BASIC_GEORGIAN = 26,
71   U_HANGUL_JAMO = 28,
72   U_LATIN_EXTENDED_ADDITIONAL = 29,
73   U_GREEK_EXTENDED = 30,
74   U_GENERAL_PUNCTUATION = 31,
75   U_SUPERSCRIPTS_AND_SUBSCRIPTS = 32,
76   U_CURRENCY_SYMBOLS = 33,
77   U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS = 34,
78   U_LETTERLIKE_SYMBOLS = 35,
79   U_NUMBER_FORMS = 36,
80   U_ARROWS = 37,
81   U_MATHEMATICAL_OPERATORS = 38,
82   U_MISCELLANEOUS_TECHNICAL = 39,
83   U_CONTROL_PICTURES = 40,
84   U_OPTICAL_CHARACTER_RECOGNITION = 41,
85   U_ENCLOSED_ALPHANUMERICS = 42,
86   U_BOX_DRAWING = 43,
87   U_BLOCK_ELEMENTS = 44,
88   U_GEOMETRIC_SHAPES = 45,
89   U_MISCELLANEOUS_SYMBOLS = 46,
90   U_DINGBATS = 47,
91   U_CJK_SYMBOLS_AND_PUNCTUATION = 48,
92   U_HIRAGANA = 49,
93   U_KATAKANA = 50,
94   U_BOPOMOFO = 51,
95   U_HANGUL_COMPATIBILITY_JAMO = 52,
96   U_CJK_MISCELLANEOUS = 53,
97   U_ENCLOSED_CJK = 54,
98   U_CJK_COMPATIBILITY = 55,
99   U_HANGUL = 56,
100   U_HANGUL_SUPPLEMENTARY_A = 57,
101   U_HANGUL_SUPPLEMENTARY_B = 58,
102   U_CJK_UNIFIED_IDEOGRAPHS = 59,
103   U_PRIVATE_USE_AREA = 60,
104   U_CJK_COMPATIBILITY_IDEOGRAPHS = 61,
105   U_ALPHABETIC_PRESENTATION_FORMS = 62,
106   U_ARABIC_PRESENTATION_FORMS_A = 63,
107   U_COMBINING_HALF_MARKS = 64,
108   U_CJK_COMPATIBILITY_FORMS = 65,
109   U_SMALL_FORM_VARIANTS = 66,
110   U_ARABIC_PRESENTATION_FORMS_B = 67,
111   U_SPECIALS = 69,
112   U_HALFWIDTH_AND_FULLWIDTH_FORMS = 68,
113   U_LAST_PLUS_ONE
114 } wxUnicodeSubsetCodes;
115 
116 /* Unicode subsets */
117 #ifdef __UNICODE__
118 
119 static struct
120 {
121     int m_low, m_high;
122     wxUnicodeSubsetCodes m_subset;
123     const wxChar* m_name;
124 } g_UnicodeSubsetTable[] =
125 {
126   { 0x0000, 0x007E,
127     U_BASIC_LATIN, wxT("Basic Latin") },
128   { 0x00A0, 0x00FF,
129     U_LATIN_1_SUPPLEMENT, wxT("Latin-1 Supplement") },
130   { 0x0100, 0x017F,
131     U_LATIN_EXTENDED_A, wxT("Latin Extended-A") },
132   { 0x0180, 0x024F,
133     U_LATIN_EXTENDED_B, wxT("Latin Extended-B") },
134   { 0x0250, 0x02AF,
135     U_IPA_EXTENSIONS, wxT("IPA Extensions") },
136   { 0x02B0, 0x02FF,
137     U_SPACING_MODIFIER_LETTERS, wxT("Spacing Modifier Letters") },
138   { 0x0300, 0x036F,
139     U_COMBINING_DIACRITICAL_MARKS, wxT("Combining Diacritical Marks") },
140   { 0x0370, 0x03CF,
141     U_BASIC_GREEK, wxT("Basic Greek") },
142   { 0x03D0, 0x03FF,
143     U_GREEK_SYMBOLS_AND_COPTIC, wxT("Greek Symbols and Coptic") },
144   { 0x0400, 0x04FF,
145     U_CYRILLIC, wxT("Cyrillic") },
146   { 0x0530, 0x058F,
147     U_ARMENIAN, wxT("Armenian") },
148   { 0x0590, 0x05CF,
149     U_HEBREW_EXTENDED, wxT("Hebrew Extended") },
150   { 0x05D0, 0x05FF,
151     U_BASIC_HEBREW, wxT("Basic Hebrew") },
152   { 0x0600, 0x0652,
153     U_BASIC_ARABIC, wxT("Basic Arabic") },
154   { 0x0653, 0x06FF,
155     U_ARABIC_EXTENDED, wxT("Arabic Extended") },
156   { 0x0900, 0x097F,
157     U_DEVANAGARI, wxT("Devanagari") },
158   { 0x0980, 0x09FF,
159     U_BENGALI, wxT("Bengali") },
160   { 0x0A00, 0x0A7F,
161     U_GURMUKHI, wxT("Gurmukhi") },
162   { 0x0A80, 0x0AFF,
163     U_GUJARATI, wxT("Gujarati") },
164   { 0x0B00, 0x0B7F,
165     U_ORIYA, wxT("Oriya") },
166   { 0x0B80, 0x0BFF,
167     U_TAMIL, wxT("Tamil") },
168   { 0x0C00, 0x0C7F,
169     U_TELUGU, wxT("Telugu") },
170   { 0x0C80, 0x0CFF,
171     U_KANNADA, wxT("Kannada") },
172   { 0x0D00, 0x0D7F,
173     U_MALAYALAM, wxT("Malayalam") },
174   { 0x0E00, 0x0E7F,
175     U_THAI, wxT("Thai") },
176   { 0x0E80, 0x0EFF,
177     U_LAO, wxT("Lao") },
178   { 0x10A0, 0x10CF,
179     U_GEORGIAN_EXTENDED, wxT("Georgian Extended") },
180   { 0x10D0, 0x10FF,
181     U_BASIC_GEORGIAN, wxT("Basic Georgian") },
182   { 0x1100, 0x11FF,
183     U_HANGUL_JAMO, wxT("Hangul Jamo") },
184   { 0x1E00, 0x1EFF,
185     U_LATIN_EXTENDED_ADDITIONAL, wxT("Latin Extended Additional") },
186   { 0x1F00, 0x1FFF,
187     U_GREEK_EXTENDED, wxT("Greek Extended") },
188   { 0x2000, 0x206F,
189     U_GENERAL_PUNCTUATION, wxT("General Punctuation") },
190   { 0x2070, 0x209F,
191     U_SUPERSCRIPTS_AND_SUBSCRIPTS, wxT("Superscripts and Subscripts") },
192   { 0x20A0, 0x20CF,
193     U_CURRENCY_SYMBOLS, wxT("Currency Symbols") },
194   { 0x20D0, 0x20FF,
195     U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS, wxT("Combining Diacritical Marks for Symbols") },
196   { 0x2100, 0x214F,
197     U_LETTERLIKE_SYMBOLS, wxT("Letterlike Symbols") },
198   { 0x2150, 0x218F,
199     U_NUMBER_FORMS, wxT("Number Forms") },
200   { 0x2190, 0x21FF,
201     U_ARROWS, wxT("Arrows") },
202   { 0x2200, 0x22FF,
203     U_MATHEMATICAL_OPERATORS, wxT("Mathematical Operators") },
204   { 0x2300, 0x23FF,
205     U_MISCELLANEOUS_TECHNICAL, wxT("Miscellaneous Technical") },
206   { 0x2400, 0x243F,
207     U_CONTROL_PICTURES, wxT("Control Pictures") },
208   { 0x2440, 0x245F,
209     U_OPTICAL_CHARACTER_RECOGNITION, wxT("Optical Character Recognition") },
210   { 0x2460, 0x24FF,
211     U_ENCLOSED_ALPHANUMERICS, wxT("Enclosed Alphanumerics") },
212   { 0x2500, 0x257F,
213     U_BOX_DRAWING, wxT("Box Drawing") },
214   { 0x2580, 0x259F,
215     U_BLOCK_ELEMENTS, wxT("Block Elements") },
216   { 0x25A0, 0x25FF,
217     U_GEOMETRIC_SHAPES, wxT("Geometric Shapes") },
218   { 0x2600, 0x26FF,
219     U_MISCELLANEOUS_SYMBOLS, wxT("Miscellaneous Symbols") },
220   { 0x2700, 0x27BF,
221     U_DINGBATS, wxT("Dingbats") },
222   { 0x3000, 0x303F,
223     U_CJK_SYMBOLS_AND_PUNCTUATION, wxT("CJK Symbols and Punctuation") },
224   { 0x3040, 0x309F,
225     U_HIRAGANA, wxT("Hiragana") },
226   { 0x30A0, 0x30FF,
227     U_KATAKANA, wxT("Katakana") },
228   { 0x3100, 0x312F,
229     U_BOPOMOFO, wxT("Bopomofo") },
230   { 0x3130, 0x318F,
231     U_HANGUL_COMPATIBILITY_JAMO, wxT("Hangul Compatibility Jamo") },
232   { 0x3190, 0x319F,
233     U_CJK_MISCELLANEOUS, wxT("CJK Miscellaneous") },
234   { 0x3200, 0x32FF,
235     U_ENCLOSED_CJK, wxT("Enclosed CJK") },
236   { 0x3300, 0x33FF,
237     U_CJK_COMPATIBILITY, wxT("CJK Compatibility") },
238   { 0x3400, 0x4DB5,
239     U_CJK_UNIFIED_IDEOGRAPHS, wxT("CJK Unified Ideographs Extension A") },
240   { 0x4E00, 0x9FFF,
241     U_CJK_UNIFIED_IDEOGRAPHS, wxT("CJK Unified Ideographs") },
242   { 0xAC00, 0xD7A3,
243     U_HANGUL, wxT("Hangul Syllables") },
244   { 0xE000, 0xF8FF,
245     U_PRIVATE_USE_AREA, wxT("Private Use Area") },
246   { 0xF900, 0xFAFF,
247     U_CJK_COMPATIBILITY_IDEOGRAPHS, wxT("CJK Compatibility Ideographs") },
248   { 0xFB00, 0xFB4F,
249     U_ALPHABETIC_PRESENTATION_FORMS, wxT("Alphabetic Presentation Forms") },
250   { 0xFB50, 0xFDFF,
251     U_ARABIC_PRESENTATION_FORMS_A, wxT("Arabic Presentation Forms-A") },
252   { 0xFE20, 0xFE2F,
253     U_COMBINING_HALF_MARKS, wxT("Combining Half Marks") },
254   { 0xFE30, 0xFE4F,
255     U_CJK_COMPATIBILITY_FORMS, wxT("CJK Compatibility Forms") },
256   { 0xFE50, 0xFE6F,
257     U_SMALL_FORM_VARIANTS, wxT("Small Form Variants") },
258   { 0xFE70, 0xFEFE,
259     U_ARABIC_PRESENTATION_FORMS_B, wxT("Arabic Presentation Forms-B") },
260   { 0xFEFF, 0xFEFF,
261     U_SPECIALS, wxT("Specials") },
262   { 0xFF00, 0xFFEF,
263     U_HALFWIDTH_AND_FULLWIDTH_FORMS, wxT("Halfwidth and Fullwidth Forms") },
264   { 0xFFF0, 0xFFFD,
265     U_SPECIALS, wxT("Specials") }
266 };
267 
268 #endif // __UNICODE__
269 
270 #if 0
271 // Not yet used, but could be used to test under Win32 whether this subset is available
272 // for the given font. The Win32 function is allegedly not accurate, however.
273 bool wxSubsetValidForFont(int subsetIndex, FONTSIGNATURE *fontSig)
274 {
275     return (fontSig->fsUsb[g_UnicodeSubsetTable[subsetIndex].m_subset/32] & (1 << (g_UnicodeSubsetTable[subsetIndex].m_subset % 32)));
276 }
277 #endif
278 
279 bool wxSymbolPickerDialog::sm_showToolTips = false;
280 
281 /*!
282  * wxSymbolPickerDialog type definition
283  */
284 
IMPLEMENT_DYNAMIC_CLASS(wxSymbolPickerDialog,wxDialog)285 IMPLEMENT_DYNAMIC_CLASS( wxSymbolPickerDialog, wxDialog )
286 
287 /*!
288  * wxSymbolPickerDialog event table definition
289  */
290 
291 BEGIN_EVENT_TABLE( wxSymbolPickerDialog, wxDialog )
292     EVT_LISTBOX(ID_SYMBOLPICKERDIALOG_LISTCTRL, wxSymbolPickerDialog::OnSymbolSelected)
293 
294 ////@begin wxSymbolPickerDialog event table entries
295     EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_FONT, wxSymbolPickerDialog::OnFontCtrlSelected )
296 
297 #if defined(__UNICODE__)
298     EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_SUBSET, wxSymbolPickerDialog::OnSubsetSelected )
299 #endif
300 
301 #if defined(__UNICODE__)
302     EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_FROM, wxSymbolPickerDialog::OnFromUnicodeSelected )
303 #endif
304 
305 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXPM__) || defined(__WXMGL__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || defined(__WXX11__) || defined(__WXPALMOS__)
306     EVT_UPDATE_UI( wxID_OK, wxSymbolPickerDialog::OnOkUpdate )
307 #endif
308 
309 #if defined(__WXMAC__)
310     EVT_UPDATE_UI( wxID_OK, wxSymbolPickerDialog::OnOkUpdate )
311 #endif
312 
313 ////@end wxSymbolPickerDialog event table entries
314 
315 END_EVENT_TABLE()
316 
317 /*!
318  * wxSymbolPickerDialog constructors
319  */
320 
321 wxSymbolPickerDialog::wxSymbolPickerDialog( )
322 {
323     Init();
324 }
325 
wxSymbolPickerDialog(const wxString & symbol,const wxString & fontName,const wxString & normalTextFont,wxWindow * parent,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)326 wxSymbolPickerDialog::wxSymbolPickerDialog( const wxString& symbol, const wxString& fontName, const wxString& normalTextFont, wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
327 {
328     Init();
329     Create(symbol, fontName, normalTextFont, parent, id, caption, pos, size, style);
330 }
331 
332 /*!
333  * wxSymbolPickerDialog creator
334  */
335 
Create(const wxString & symbol,const wxString & fontName,const wxString & normalTextFont,wxWindow * parent,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)336 bool wxSymbolPickerDialog::Create( const wxString& symbol, const wxString& fontName, const wxString& normalTextFont, wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
337 {
338     m_fontName = fontName;
339     m_normalTextFontName = normalTextFont;
340     m_symbol = symbol;
341 
342 ////@begin wxSymbolPickerDialog creation
343     SetExtraStyle(wxWS_EX_BLOCK_EVENTS|wxDIALOG_EX_CONTEXTHELP);
344     wxDialog::Create( parent, id, caption, pos, size, style );
345 
346     CreateControls();
347     if (GetSizer())
348     {
349         GetSizer()->SetSizeHints(this);
350     }
351     Centre();
352 ////@end wxSymbolPickerDialog creation
353     return true;
354 }
355 
356 /*!
357  * Member initialisation for wxSymbolPickerDialog
358  */
359 
Init()360 void wxSymbolPickerDialog::Init()
361 {
362 ////@begin wxSymbolPickerDialog member initialisation
363     m_fromUnicode = true;
364     m_fontCtrl = NULL;
365 #if defined(__UNICODE__)
366     m_subsetCtrl = NULL;
367 #endif
368     m_symbolsCtrl = NULL;
369     m_symbolStaticCtrl = NULL;
370     m_characterCodeCtrl = NULL;
371 #if defined(__UNICODE__)
372     m_fromUnicodeCtrl = NULL;
373 #endif
374 ////@end wxSymbolPickerDialog member initialisation
375     m_dontUpdate = false;
376 }
377 
378 /*!
379  * Control creation for wxSymbolPickerDialog
380  */
381 
CreateControls()382 void wxSymbolPickerDialog::CreateControls()
383 {
384 #ifdef __WXMAC__
385     SetWindowVariant(wxWINDOW_VARIANT_SMALL);
386 #endif
387 
388 ////@begin wxSymbolPickerDialog content construction
389     wxSymbolPickerDialog* itemDialog1 = this;
390 
391     wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
392     itemDialog1->SetSizer(itemBoxSizer2);
393 
394     wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxVERTICAL);
395     itemBoxSizer2->Add(itemBoxSizer3, 1, wxGROW|wxALL, 5);
396 
397     wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
398     itemBoxSizer3->Add(itemBoxSizer4, 0, wxGROW, 5);
399 
400     wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
401     itemBoxSizer4->Add(itemBoxSizer5, 1, wxGROW, 5);
402 
403     wxStaticText* itemStaticText6 = new wxStaticText( itemDialog1, wxID_STATIC, _("&Font:"), wxDefaultPosition, wxDefaultSize, 0 );
404     itemBoxSizer5->Add(itemStaticText6, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
405 
406     wxArrayString m_fontCtrlStrings;
407     m_fontCtrl = new wxComboBox( itemDialog1, ID_SYMBOLPICKERDIALOG_FONT, wxEmptyString, wxDefaultPosition, wxSize(240, -1), m_fontCtrlStrings, wxCB_READONLY );
408     m_fontCtrl->SetHelpText(_("The font from which to take the symbol."));
409     if (wxSymbolPickerDialog::ShowToolTips())
410         m_fontCtrl->SetToolTip(_("The font from which to take the symbol."));
411     itemBoxSizer5->Add(m_fontCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
412 
413     itemBoxSizer5->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
414 
415 #if defined(__UNICODE__)
416     wxStaticText* itemStaticText9 = new wxStaticText( itemDialog1, wxID_STATIC, _("&Subset:"), wxDefaultPosition, wxDefaultSize, 0 );
417     itemBoxSizer5->Add(itemStaticText9, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
418 
419 #endif
420 
421 #if defined(__UNICODE__)
422     wxArrayString m_subsetCtrlStrings;
423     m_subsetCtrl = new wxComboBox( itemDialog1, ID_SYMBOLPICKERDIALOG_SUBSET, wxEmptyString, wxDefaultPosition, wxDefaultSize, m_subsetCtrlStrings, wxCB_READONLY );
424     m_subsetCtrl->SetHelpText(_("Shows a Unicode subset."));
425     if (wxSymbolPickerDialog::ShowToolTips())
426         m_subsetCtrl->SetToolTip(_("Shows a Unicode subset."));
427     itemBoxSizer5->Add(m_subsetCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
428 
429 #endif
430 
431     m_symbolsCtrl = new wxSymbolListCtrl( itemDialog1, ID_SYMBOLPICKERDIALOG_LISTCTRL, wxDefaultPosition, wxSize(500, 220), 0 );
432     itemBoxSizer3->Add(m_symbolsCtrl, 1, wxGROW|wxALL, 5);
433 
434     wxBoxSizer* itemBoxSizer12 = new wxBoxSizer(wxHORIZONTAL);
435     itemBoxSizer3->Add(itemBoxSizer12, 0, wxGROW, 5);
436 
437     m_symbolStaticCtrl = new wxStaticText( itemDialog1, wxID_STATIC, _("xxxx"), wxDefaultPosition, wxSize(40, -1), wxALIGN_CENTRE );
438     itemBoxSizer12->Add(m_symbolStaticCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
439 
440     itemBoxSizer12->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
441 
442     wxStaticText* itemStaticText15 = new wxStaticText( itemDialog1, wxID_STATIC, _("&Character code:"), wxDefaultPosition, wxDefaultSize, 0 );
443     itemBoxSizer12->Add(itemStaticText15, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
444 
445     m_characterCodeCtrl = new wxTextCtrl( itemDialog1, ID_SYMBOLPICKERDIALOG_CHARACTERCODE, wxEmptyString, wxDefaultPosition, wxSize(140, -1), wxTE_READONLY|wxTE_CENTRE );
446     m_characterCodeCtrl->SetHelpText(_("The character code."));
447     if (wxSymbolPickerDialog::ShowToolTips())
448         m_characterCodeCtrl->SetToolTip(_("The character code."));
449     itemBoxSizer12->Add(m_characterCodeCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
450 
451     itemBoxSizer12->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
452 
453 #if defined(__UNICODE__)
454     wxStaticText* itemStaticText18 = new wxStaticText( itemDialog1, wxID_STATIC, _("&From:"), wxDefaultPosition, wxDefaultSize, 0 );
455     itemBoxSizer12->Add(itemStaticText18, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
456 
457 #endif
458 
459 #if defined(__UNICODE__)
460     wxArrayString m_fromUnicodeCtrlStrings;
461     m_fromUnicodeCtrlStrings.Add(_("ASCII"));
462     m_fromUnicodeCtrlStrings.Add(_("Unicode"));
463     m_fromUnicodeCtrl = new wxComboBox( itemDialog1, ID_SYMBOLPICKERDIALOG_FROM, _("Unicode"), wxDefaultPosition, wxDefaultSize, m_fromUnicodeCtrlStrings, wxCB_READONLY );
464     m_fromUnicodeCtrl->SetStringSelection(_("Unicode"));
465     m_fromUnicodeCtrl->SetHelpText(_("The range to show."));
466     if (wxSymbolPickerDialog::ShowToolTips())
467         m_fromUnicodeCtrl->SetToolTip(_("The range to show."));
468     itemBoxSizer12->Add(m_fromUnicodeCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
469 
470 #endif
471 
472 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXPM__) || defined(__WXMGL__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || defined(__WXX11__) || defined(__WXPALMOS__)
473     wxBoxSizer* itemBoxSizer20 = new wxBoxSizer(wxHORIZONTAL);
474     itemBoxSizer3->Add(itemBoxSizer20, 0, wxGROW, 5);
475 
476     itemBoxSizer20->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
477 
478     wxButton* itemButton22 = new wxButton( itemDialog1, wxID_OK, _("Insert"), wxDefaultPosition, wxDefaultSize, 0 );
479     itemButton22->SetDefault();
480     itemButton22->SetHelpText(_("Inserts the chosen symbol."));
481     if (wxSymbolPickerDialog::ShowToolTips())
482         itemButton22->SetToolTip(_("Inserts the chosen symbol."));
483     itemBoxSizer20->Add(itemButton22, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
484 
485     wxButton* itemButton23 = new wxButton( itemDialog1, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
486     itemButton23->SetHelpText(_("Closes the dialog without inserting a symbol."));
487     if (wxSymbolPickerDialog::ShowToolTips())
488         itemButton23->SetToolTip(_("Closes the dialog without inserting a symbol."));
489     itemBoxSizer20->Add(itemButton23, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
490 
491 #endif
492 
493 #if defined(__WXMAC__)
494     wxBoxSizer* itemBoxSizer24 = new wxBoxSizer(wxHORIZONTAL);
495     itemBoxSizer3->Add(itemBoxSizer24, 0, wxGROW, 5);
496 
497     itemBoxSizer24->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
498 
499     wxButton* itemButton26 = new wxButton( itemDialog1, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
500     itemButton26->SetHelpText(_("Closes the dialog without inserting a symbol."));
501     if (wxSymbolPickerDialog::ShowToolTips())
502         itemButton26->SetToolTip(_("Closes the dialog without inserting a symbol."));
503     itemBoxSizer24->Add(itemButton26, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
504 
505     wxButton* itemButton27 = new wxButton( itemDialog1, wxID_OK, _("Insert"), wxDefaultPosition, wxDefaultSize, 0 );
506     itemButton27->SetDefault();
507     itemButton27->SetHelpText(_("Inserts the chosen symbol."));
508     if (wxSymbolPickerDialog::ShowToolTips())
509         itemButton27->SetToolTip(_("Inserts the chosen symbol."));
510     itemBoxSizer24->Add(itemButton27, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
511 
512 #endif
513 
514 ////@end wxSymbolPickerDialog content construction
515 
516 }
517 
518 /// Data transfer
TransferDataToWindow()519 bool wxSymbolPickerDialog::TransferDataToWindow()
520 {
521     m_dontUpdate = true;
522 
523     if (m_fontCtrl->GetCount() == 0)
524     {
525         wxArrayString faceNames = wxRichTextCtrl::GetAvailableFontNames();
526         faceNames.Sort();
527 
528         faceNames.Insert(_("(Normal text)"), 0);
529         m_fontCtrl->Append(faceNames);
530     }
531 
532     if (m_fontName.empty())
533         m_fontCtrl->SetSelection(0);
534     else
535     {
536         if (m_fontCtrl->FindString(m_fontName) != wxNOT_FOUND)
537             m_fontCtrl->SetStringSelection(m_fontName);
538         else
539             m_fontCtrl->SetSelection(0);
540     }
541 
542 #if defined(__UNICODE__)
543     if (m_subsetCtrl->GetCount() == 0)
544     {
545         // Insert items into subset combo
546         int i;
547         for (i = 0; i < (int) (sizeof(g_UnicodeSubsetTable)/sizeof(g_UnicodeSubsetTable[0])); i++)
548         {
549             m_subsetCtrl->Append(g_UnicodeSubsetTable[i].m_name);
550         }
551         m_subsetCtrl->SetSelection(0);
552     }
553 #endif
554 
555 #if defined(__UNICODE__)
556     m_symbolsCtrl->SetUnicodeMode(m_fromUnicode);
557 #endif
558 
559     if (!m_symbol.empty())
560     {
561         int sel = (int) m_symbol[0];
562         m_symbolsCtrl->SetSelection(sel);
563     }
564 
565     UpdateSymbolDisplay();
566 
567     m_dontUpdate = false;
568 
569     return true;
570 }
571 
UpdateSymbolDisplay(bool updateSymbolList,bool showAtSubset)572 void wxSymbolPickerDialog::UpdateSymbolDisplay(bool updateSymbolList, bool showAtSubset)
573 {
574     wxFont font;
575     wxString fontNameToUse;
576     if (m_fontName.empty())
577         fontNameToUse = m_normalTextFontName;
578     else
579         fontNameToUse = m_fontName;
580 
581     if (!fontNameToUse.empty())
582     {
583         font = wxFont(14, wxDEFAULT, wxNORMAL, wxNORMAL, false, fontNameToUse);
584     }
585     else
586         font = *wxNORMAL_FONT;
587 
588     if (updateSymbolList)
589     {
590         m_symbolsCtrl->SetFont(font);
591     }
592 
593     if (!m_symbol.empty())
594     {
595         m_symbolStaticCtrl->SetFont(font);
596         m_symbolStaticCtrl->SetLabel(m_symbol);
597 
598         int symbol = (int) m_symbol[0];
599         m_characterCodeCtrl->SetValue(wxString::Format(wxT("%X hex (%d dec)"), symbol, symbol));
600     }
601     else
602     {
603         m_symbolStaticCtrl->SetLabel(wxEmptyString);
604         m_characterCodeCtrl->SetValue(wxEmptyString);
605     }
606 
607 #if defined(__UNICODE__)
608     if (showAtSubset)
609         ShowAtSubset();
610 #else
611     wxUnusedVar(showAtSubset);
612 #endif
613 }
614 
615 /// Show at the current subset selection
ShowAtSubset()616 void wxSymbolPickerDialog::ShowAtSubset()
617 {
618 #if defined(__UNICODE__)
619     if (m_fromUnicode)
620     {
621         int sel = m_subsetCtrl->GetSelection();
622         int low = g_UnicodeSubsetTable[sel].m_low;
623         m_symbolsCtrl->EnsureVisible(low);
624     }
625 #endif
626 }
627 
628 // Handle font selection
OnFontCtrlSelected(wxCommandEvent & WXUNUSED (event))629 void wxSymbolPickerDialog::OnFontCtrlSelected( wxCommandEvent& WXUNUSED(event) )
630 {
631     if (m_fontCtrl->GetSelection() == 0)
632         m_fontName = wxEmptyString;
633     else
634         m_fontName = m_fontCtrl->GetStringSelection();
635 
636     UpdateSymbolDisplay();
637 }
638 
639 /// Respond to symbol selection
OnSymbolSelected(wxCommandEvent & event)640 void wxSymbolPickerDialog::OnSymbolSelected( wxCommandEvent& event )
641 {
642     if (m_dontUpdate)
643         return;
644 
645     int sel = event.GetSelection();
646     if (sel == wxNOT_FOUND)
647         m_symbol = wxEmptyString;
648     else
649     {
650         m_symbol = wxEmptyString;
651         m_symbol << (wxChar) sel;
652     }
653 
654 #if defined(__UNICODE__)
655     if (sel != -1 && m_fromUnicode)
656     {
657         // Need to make the subset selection reflect the current symbol
658         int i;
659         for (i = 0; i < (int) (sizeof(g_UnicodeSubsetTable)/sizeof(g_UnicodeSubsetTable[0])); i++)
660         {
661             if (sel >= g_UnicodeSubsetTable[i].m_low && sel <= g_UnicodeSubsetTable[i].m_high)
662             {
663                 m_dontUpdate = true;
664                 m_subsetCtrl->SetSelection(i);
665                 m_dontUpdate = false;
666                 break;
667             }
668         }
669     }
670 #endif
671 
672     UpdateSymbolDisplay(false, false);
673 }
674 
675 #if defined(__UNICODE__)
676 // Handle Unicode/ASCII selection
OnFromUnicodeSelected(wxCommandEvent & WXUNUSED (event))677 void wxSymbolPickerDialog::OnFromUnicodeSelected( wxCommandEvent& WXUNUSED(event) )
678 {
679     if (m_dontUpdate)
680         return;
681 
682     m_fromUnicode = (m_fromUnicodeCtrl->GetSelection() == 1);
683     m_symbolsCtrl->SetUnicodeMode(m_fromUnicode);
684     UpdateSymbolDisplay(false);
685 }
686 
687 // Handle subset selection
OnSubsetSelected(wxCommandEvent & WXUNUSED (event))688 void wxSymbolPickerDialog::OnSubsetSelected( wxCommandEvent& WXUNUSED(event) )
689 {
690     if (m_dontUpdate)
691         return;
692 
693     ShowAtSubset();
694 }
695 #endif
696 
697 /*!
698  * wxEVT_UPDATE_UI event handler for wxID_OK
699  */
700 
OnOkUpdate(wxUpdateUIEvent & event)701 void wxSymbolPickerDialog::OnOkUpdate( wxUpdateUIEvent& event )
702 {
703     event.Enable(HasSelection());
704 }
705 
706 /// Set Unicode mode
SetUnicodeMode(bool unicodeMode)707 void wxSymbolPickerDialog::SetUnicodeMode(bool unicodeMode)
708 {
709 #if defined(__UNICODE__)
710     m_dontUpdate = true;
711     m_fromUnicode = unicodeMode;
712     if (m_fromUnicodeCtrl)
713         m_fromUnicodeCtrl->SetSelection(m_fromUnicode ? 1 : 0);
714     UpdateSymbolDisplay();
715     m_dontUpdate = false;
716 #else
717     wxUnusedVar(unicodeMode);
718 #endif
719 }
720 
721 /// Get the selected symbol character
GetSymbolChar() const722 int wxSymbolPickerDialog::GetSymbolChar() const
723 {
724     if (m_symbol.empty())
725         return -1;
726     else
727         return (int) m_symbol[0];
728 }
729 
730 
731 /*!
732  * Get bitmap resources
733  */
734 
GetBitmapResource(const wxString & name)735 wxBitmap wxSymbolPickerDialog::GetBitmapResource( const wxString& name )
736 {
737     // Bitmap retrieval
738 ////@begin wxSymbolPickerDialog bitmap retrieval
739     wxUnusedVar(name);
740     return wxNullBitmap;
741 ////@end wxSymbolPickerDialog bitmap retrieval
742 }
743 
744 /*!
745  * Get icon resources
746  */
747 
GetIconResource(const wxString & name)748 wxIcon wxSymbolPickerDialog::GetIconResource( const wxString& name )
749 {
750     // Icon retrieval
751 ////@begin wxSymbolPickerDialog icon retrieval
752     wxUnusedVar(name);
753     return wxNullIcon;
754 ////@end wxSymbolPickerDialog icon retrieval
755 }
756 
757 /*!
758  * The scrolling symbol list.
759  */
760 
761 // ----------------------------------------------------------------------------
762 // event tables
763 // ----------------------------------------------------------------------------
764 
BEGIN_EVENT_TABLE(wxSymbolListCtrl,wxVScrolledWindow)765 BEGIN_EVENT_TABLE(wxSymbolListCtrl, wxVScrolledWindow)
766     EVT_PAINT(wxSymbolListCtrl::OnPaint)
767     EVT_SIZE(wxSymbolListCtrl::OnSize)
768 
769     EVT_KEY_DOWN(wxSymbolListCtrl::OnKeyDown)
770     EVT_LEFT_DOWN(wxSymbolListCtrl::OnLeftDown)
771     EVT_LEFT_DCLICK(wxSymbolListCtrl::OnLeftDClick)
772 END_EVENT_TABLE()
773 
774 // ============================================================================
775 // implementation
776 // ============================================================================
777 
778 IMPLEMENT_ABSTRACT_CLASS(wxSymbolListCtrl, wxVScrolledWindow)
779 
780 // ----------------------------------------------------------------------------
781 // wxSymbolListCtrl creation
782 // ----------------------------------------------------------------------------
783 
784 void wxSymbolListCtrl::Init()
785 {
786     m_current = wxNOT_FOUND;
787     m_doubleBuffer = NULL;
788     m_cellSize = wxSize(40, 40);
789     m_minSymbolValue = 0;
790     m_maxSymbolValue = 255;
791     m_symbolsPerLine = 0;
792     m_unicodeMode = false;
793 }
794 
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)795 bool wxSymbolListCtrl::Create(wxWindow *parent,
796                         wxWindowID id,
797                         const wxPoint& pos,
798                         const wxSize& size,
799                         long style,
800                         const wxString& name)
801 {
802     style |= wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE;
803 
804     if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
805 #ifdef __WXMSW__
806         style |= GetThemedBorderStyle();
807 #else
808         style |= wxBORDER_SUNKEN;
809 #endif
810 
811     if ( !wxVScrolledWindow::Create(parent, id, pos, size, style, name) )
812         return false;
813 
814     // make sure the native widget has the right colour since we do
815     // transparent drawing by default
816     SetBackgroundColour(GetBackgroundColour());
817     m_colBgSel = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
818 
819     // flicker-free drawing requires this
820     SetBackgroundStyle(wxBG_STYLE_CUSTOM);
821 
822     SetFont(*wxNORMAL_FONT);
823 
824     SetupCtrl();
825 
826     return true;
827 }
828 
~wxSymbolListCtrl()829 wxSymbolListCtrl::~wxSymbolListCtrl()
830 {
831     delete m_doubleBuffer;
832 }
833 
834 // ----------------------------------------------------------------------------
835 // selection handling
836 // ----------------------------------------------------------------------------
837 
IsSelected(int item) const838 bool wxSymbolListCtrl::IsSelected(int item) const
839 {
840     return item == m_current;
841 }
842 
DoSetCurrent(int current)843 bool wxSymbolListCtrl::DoSetCurrent(int current)
844 {
845     wxASSERT_MSG( current == wxNOT_FOUND ||
846                     (current >= m_minSymbolValue && current <= m_maxSymbolValue),
847                   _T("wxSymbolListCtrl::DoSetCurrent(): invalid symbol value") );
848 
849     if ( current == m_current )
850     {
851         // nothing to do
852         return false;
853     }
854 
855     if ( m_current != wxNOT_FOUND )
856         RefreshLine(SymbolValueToLineNumber(m_current));
857 
858     m_current = current;
859 
860     if ( m_current != wxNOT_FOUND )
861     {
862         int lineNo = SymbolValueToLineNumber(m_current);
863 
864         // if the line is not visible at all, we scroll it into view but we
865         // don't need to refresh it -- it will be redrawn anyhow
866         if ( !IsVisible(lineNo) )
867         {
868             ScrollToLine(lineNo);
869         }
870         else // line is at least partly visible
871         {
872             // it is, indeed, only partly visible, so scroll it into view to
873             // make it entirely visible
874             while ( unsigned(lineNo) == GetLastVisibleLine() &&
875                     ScrollToLine(GetVisibleBegin()+1) )
876                 ;
877 
878             // but in any case refresh it as even if it was only partly visible
879             // before we need to redraw it entirely as its background changed
880             RefreshLine(lineNo);
881         }
882     }
883 
884     return true;
885 }
886 
SendSelectedEvent()887 void wxSymbolListCtrl::SendSelectedEvent()
888 {
889     wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, GetId());
890     event.SetEventObject(this);
891     event.SetInt(m_current);
892 
893     (void)GetEventHandler()->ProcessEvent(event);
894 }
895 
SetSelection(int selection)896 void wxSymbolListCtrl::SetSelection(int selection)
897 {
898     wxCHECK_RET( selection == wxNOT_FOUND ||
899                   (selection >= m_minSymbolValue && selection < m_maxSymbolValue),
900                   _T("wxSymbolListCtrl::SetSelection(): invalid symbol value") );
901 
902     DoSetCurrent(selection);
903 }
904 
905 // ----------------------------------------------------------------------------
906 // wxSymbolListCtrl appearance parameters
907 // ----------------------------------------------------------------------------
908 
SetMargins(const wxPoint & pt)909 void wxSymbolListCtrl::SetMargins(const wxPoint& pt)
910 {
911     if ( pt != m_ptMargins )
912     {
913         m_ptMargins = pt;
914 
915         Refresh();
916     }
917 }
918 
SetSelectionBackground(const wxColour & col)919 void wxSymbolListCtrl::SetSelectionBackground(const wxColour& col)
920 {
921     m_colBgSel = col;
922 }
923 
924 // ----------------------------------------------------------------------------
925 // wxSymbolListCtrl painting
926 // ----------------------------------------------------------------------------
927 
OnGetLineHeight(size_t WXUNUSED (line)) const928 wxCoord wxSymbolListCtrl::OnGetLineHeight(size_t WXUNUSED(line)) const
929 {
930     return m_cellSize.y + 2*m_ptMargins.y + 1 /* for divider */ ;
931 }
932 
933 // draws a line of symbols
OnDrawItem(wxDC & dc,const wxRect & rect,size_t n) const934 void wxSymbolListCtrl::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
935 {
936     wxColour oldTextColour = dc.GetTextForeground();
937     int startSymbol = n*m_symbolsPerLine;
938 
939     int i;
940     for (i = 0; i < m_symbolsPerLine; i++)
941     {
942         bool resetColour = false;
943         int symbol = startSymbol+i;
944         if (symbol == m_current)
945         {
946             dc.SetBrush(wxBrush(m_colBgSel));
947 
948             dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
949             resetColour = true;
950 
951             wxPen oldPen = dc.GetPen();
952             dc.SetPen(*wxTRANSPARENT_PEN);
953 
954             dc.DrawRectangle(rect.x + i*m_cellSize.x, rect.y, m_cellSize.x, rect.y+rect.height);
955             dc.SetPen(oldPen);
956         }
957 
958         // Don't draw first line
959         if (i != 0)
960             dc.DrawLine(rect.x + i*m_cellSize.x, rect.y, i*m_cellSize.x, rect.y+rect.height);
961 
962         if (symbol >= m_minSymbolValue && symbol <= m_maxSymbolValue)
963         {
964             wxString text;
965             text << (wxChar) symbol;
966 
967             wxCoord w, h;
968             dc.GetTextExtent(text, & w, & h);
969 
970             int x = rect.x + i*m_cellSize.x + (m_cellSize.x - w)/2;
971             int y = rect.y + (m_cellSize.y - h)/2;
972             dc.DrawText(text, x, y);
973         }
974 
975         if (resetColour)
976             dc.SetTextForeground(oldTextColour);
977     }
978 
979     // Draw horizontal separator line
980     dc.DrawLine(rect.x, rect.y+rect.height-1, rect.x+rect.width, rect.y+rect.height-1);
981 }
982 
OnPaint(wxPaintEvent & WXUNUSED (event))983 void wxSymbolListCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
984 {
985     // If size is larger, recalculate double buffer bitmap
986     wxSize clientSize = GetClientSize();
987 
988     if ( !m_doubleBuffer ||
989          clientSize.x > m_doubleBuffer->GetWidth() ||
990          clientSize.y > m_doubleBuffer->GetHeight() )
991     {
992         delete m_doubleBuffer;
993         m_doubleBuffer = new wxBitmap(clientSize.x+25,clientSize.y+25);
994     }
995 
996     wxBufferedPaintDC dc(this,*m_doubleBuffer);
997 
998     // the update rectangle
999     wxRect rectUpdate = GetUpdateClientRect();
1000 
1001     // fill it with background colour
1002     dc.SetBackground(GetBackgroundColour());
1003     dc.Clear();
1004 
1005     // set the font to be displayed
1006     dc.SetFont(GetFont());
1007 
1008     // the bounding rectangle of the current line
1009     wxRect rectLine;
1010     rectLine.width = clientSize.x;
1011 
1012     dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)));
1013     dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
1014     dc.SetBackgroundMode(wxTRANSPARENT);
1015 
1016     // iterate over all visible lines
1017     const size_t lineMax = GetVisibleEnd();
1018     for ( size_t line = GetFirstVisibleLine(); line < lineMax; line++ )
1019     {
1020         const wxCoord hLine = OnGetLineHeight(line);
1021 
1022         rectLine.height = hLine;
1023 
1024         // and draw the ones which intersect the update rect
1025         if ( rectLine.Intersects(rectUpdate) )
1026         {
1027             // don't allow drawing outside of the lines rectangle
1028             wxDCClipper clip(dc, rectLine);
1029 
1030             wxRect rect = rectLine;
1031             rect.Deflate(m_ptMargins.x, m_ptMargins.y);
1032             OnDrawItem(dc, rect, line);
1033         }
1034         else // no intersection
1035         {
1036             if ( rectLine.GetTop() > rectUpdate.GetBottom() )
1037             {
1038                 // we are already below the update rect, no need to continue
1039                 // further
1040                 break;
1041             }
1042             //else: the next line may intersect the update rect
1043         }
1044 
1045         rectLine.y += hLine;
1046     }
1047 }
1048 
1049 // ============================================================================
1050 // wxSymbolListCtrl keyboard/mouse handling
1051 // ============================================================================
1052 
DoHandleItemClick(int item,int WXUNUSED (flags))1053 void wxSymbolListCtrl::DoHandleItemClick(int item, int WXUNUSED(flags))
1054 {
1055     if (m_current != item)
1056     {
1057         m_current = item;
1058         Refresh();
1059         SendSelectedEvent();
1060     }
1061 }
1062 
1063 // ----------------------------------------------------------------------------
1064 // keyboard handling
1065 // ----------------------------------------------------------------------------
1066 
OnKeyDown(wxKeyEvent & event)1067 void wxSymbolListCtrl::OnKeyDown(wxKeyEvent& event)
1068 {
1069     // No keyboard interface for now
1070     event.Skip();
1071 #if 0
1072     // flags for DoHandleItemClick()
1073     int flags = ItemClick_Kbd;
1074 
1075     int currentLineNow = SymbolValueToLineNumber(m_current);
1076 
1077     int currentLine;
1078     switch ( event.GetKeyCode() )
1079     {
1080         case WXK_HOME:
1081             currentLine = 0;
1082             break;
1083 
1084         case WXK_END:
1085             currentLine = GetLineCount() - 1;
1086             break;
1087 
1088         case WXK_DOWN:
1089             if ( currentLineNow == (int)GetLineCount() - 1 )
1090                 return;
1091 
1092             currentLine = currentLineNow + 1;
1093             break;
1094 
1095         case WXK_UP:
1096             if ( m_current == wxNOT_FOUND )
1097                 currentLine = GetLineCount() - 1;
1098             else if ( currentLineNow != 0 )
1099                 currentLine = currentLineNow - 1;
1100             else // currentLineNow == 0
1101                 return;
1102             break;
1103 
1104         case WXK_PAGEDOWN:
1105             PageDown();
1106             currentLine = GetFirstVisibleLine();
1107             break;
1108 
1109         case WXK_PAGEUP:
1110             if ( currentLineNow == (int)GetFirstVisibleLine() )
1111             {
1112                 PageUp();
1113             }
1114 
1115             currentLine = GetFirstVisibleLine();
1116             break;
1117 
1118         case WXK_SPACE:
1119             // hack: pressing space should work like a mouse click rather than
1120             // like a keyboard arrow press, so trick DoHandleItemClick() in
1121             // thinking we were clicked
1122             flags &= ~ItemClick_Kbd;
1123             currentLine = currentLineNow;
1124             break;
1125 
1126 #ifdef __WXMSW__
1127         case WXK_TAB:
1128             // Since we are using wxWANTS_CHARS we need to send navigation
1129             // events for the tabs on MSW
1130             {
1131                 wxNavigationKeyEvent ne;
1132                 ne.SetDirection(!event.ShiftDown());
1133                 ne.SetCurrentFocus(this);
1134                 ne.SetEventObject(this);
1135                 GetParent()->GetEventHandler()->ProcessEvent(ne);
1136             }
1137             // fall through to default
1138 #endif
1139         default:
1140             event.Skip();
1141             currentLine = 0; // just to silent the stupid compiler warnings
1142             wxUnusedVar(currentNow);
1143             return;
1144     }
1145 
1146 #if 0
1147     if ( event.ShiftDown() )
1148        flags |= ItemClick_Shift;
1149     if ( event.ControlDown() )
1150         flags |= ItemClick_Ctrl;
1151 
1152     DoHandleItemClick(current, flags);
1153 #endif
1154 #endif
1155 }
1156 
1157 // ----------------------------------------------------------------------------
1158 // wxSymbolListCtrl mouse handling
1159 // ----------------------------------------------------------------------------
1160 
OnLeftDown(wxMouseEvent & event)1161 void wxSymbolListCtrl::OnLeftDown(wxMouseEvent& event)
1162 {
1163     SetFocus();
1164 
1165     int item = HitTest(event.GetPosition());
1166 
1167     if ( item != wxNOT_FOUND )
1168     {
1169         int flags = 0;
1170         if ( event.ShiftDown() )
1171            flags |= ItemClick_Shift;
1172 
1173         // under Mac Apple-click is used in the same way as Ctrl-click
1174         // elsewhere
1175 #ifdef __WXMAC__
1176         if ( event.MetaDown() )
1177 #else
1178         if ( event.ControlDown() )
1179 #endif
1180             flags |= ItemClick_Ctrl;
1181 
1182         DoHandleItemClick(item, flags);
1183     }
1184 }
1185 
OnLeftDClick(wxMouseEvent & eventMouse)1186 void wxSymbolListCtrl::OnLeftDClick(wxMouseEvent& eventMouse)
1187 {
1188     int item = HitTest(eventMouse.GetPosition());
1189     if ( item != wxNOT_FOUND )
1190     {
1191 
1192         // if item double-clicked was not yet selected, then treat
1193         // this event as a left-click instead
1194         if ( item == m_current )
1195         {
1196             wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, GetId());
1197             event.SetEventObject(this);
1198             event.SetInt(item);
1199 
1200             (void)GetEventHandler()->ProcessEvent(event);
1201         }
1202         else
1203         {
1204             OnLeftDown(eventMouse);
1205         }
1206 
1207     }
1208 }
1209 
1210 // calculate line number from symbol value
SymbolValueToLineNumber(int item)1211 int wxSymbolListCtrl::SymbolValueToLineNumber(int item)
1212 {
1213     return (int) (item/m_symbolsPerLine);
1214 }
1215 
1216 // initialise control from current min/max values
SetupCtrl(bool scrollToSelection)1217 void wxSymbolListCtrl::SetupCtrl(bool scrollToSelection)
1218 {
1219     wxSize sz = GetClientSize();
1220 
1221     m_symbolsPerLine = sz.x/(m_cellSize.x+m_ptMargins.x);
1222     int noLines = (1 + SymbolValueToLineNumber(m_maxSymbolValue));
1223 
1224     SetLineCount(noLines);
1225     Refresh();
1226 
1227     if (scrollToSelection && m_current != wxNOT_FOUND && m_current >= m_minSymbolValue && m_current <= m_maxSymbolValue)
1228     {
1229         ScrollToLine(SymbolValueToLineNumber(m_current));
1230     }
1231 }
1232 
1233 // make this item visible
EnsureVisible(int item)1234 void wxSymbolListCtrl::EnsureVisible(int item)
1235 {
1236     if (item != wxNOT_FOUND && item >= m_minSymbolValue && item <= m_maxSymbolValue)
1237     {
1238         ScrollToLine(SymbolValueToLineNumber(item));
1239     }
1240 }
1241 
1242 
1243 // hit testing
HitTest(const wxPoint & pt)1244 int wxSymbolListCtrl::HitTest(const wxPoint& pt)
1245 {
1246     wxCoord lineHeight = OnGetLineHeight(0);
1247 
1248     int atLine = GetVisibleBegin() + (pt.y/lineHeight);
1249     int symbol = (atLine*m_symbolsPerLine) + (pt.x/(m_cellSize.x+1));
1250 
1251     if (symbol >= m_minSymbolValue && symbol <= m_maxSymbolValue)
1252         return symbol;
1253 
1254     return -1;
1255 }
1256 
1257 // Respond to size change
OnSize(wxSizeEvent & event)1258 void wxSymbolListCtrl::OnSize(wxSizeEvent& event)
1259 {
1260     SetupCtrl();
1261     event.Skip();
1262 }
1263 
1264 // set the current font
SetFont(const wxFont & font)1265 bool wxSymbolListCtrl::SetFont(const wxFont& font)
1266 {
1267     wxVScrolledWindow::SetFont(font);
1268 
1269     SetupCtrl();
1270 
1271     return true;
1272 }
1273 
1274 // set Unicode/ASCII mode
SetUnicodeMode(bool unicodeMode)1275 void wxSymbolListCtrl::SetUnicodeMode(bool unicodeMode)
1276 {
1277     bool changed = false;
1278     if (unicodeMode && !m_unicodeMode)
1279     {
1280         changed = true;
1281 
1282         m_minSymbolValue = 0;
1283         m_maxSymbolValue = 65535;
1284     }
1285     else if (!unicodeMode && m_unicodeMode)
1286     {
1287         changed = true;
1288         m_minSymbolValue = 0;
1289         m_maxSymbolValue = 255;
1290     }
1291     m_unicodeMode = unicodeMode;
1292 
1293     if (changed)
1294         SetupCtrl();
1295 }
1296 
1297 // ----------------------------------------------------------------------------
1298 // use the same default attributes as wxListBox
1299 // ----------------------------------------------------------------------------
1300 
1301 //static
1302 wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant variant)1303 wxSymbolListCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
1304 {
1305     return wxListBox::GetClassDefaultAttributes(variant);
1306 }
1307 
1308 #endif // wxUSE_RICHTEXT
1309