]> git.saurik.com Git - wxWidgets.git/blob - samples/font/font.cpp
compilation fix for recent commit
[wxWidgets.git] / samples / font / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: font.cpp
3 // Purpose: wxFont demo
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 30.09.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin
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 // for all others, include the necessary headers (this file is usually all you
20 // need because it includes almost all <standard< wxWindows headers
21 #ifndef WX_PRECOMP
22 #include "wx/wx.h"
23
24 #include "wx/log.h"
25 #endif
26
27 #include "wx/choicdlg.h"
28 #include "wx/fontdlg.h"
29 #include "wx/fontenum.h"
30 #include "wx/fontmap.h"
31 #include "wx/encconv.h"
32 #include "wx/splitter.h"
33 #include "wx/textfile.h"
34
35 // ----------------------------------------------------------------------------
36 // private classes
37 // ----------------------------------------------------------------------------
38
39 // Define a new application type, each program should derive a class from wxApp
40 class MyApp : public wxApp
41 {
42 public:
43 // override base class virtuals
44 // ----------------------------
45
46 // this one is called on application startup and is a good place for the app
47 // initialization (doing it here and not in the ctor allows to have an error
48 // return: if OnInit() returns false, the application terminates)
49 virtual bool OnInit();
50 };
51
52 // MyCanvas is a canvas on which we show the font sample
53 class MyCanvas: public wxWindow
54 {
55 public:
56 MyCanvas( wxWindow *parent );
57 ~MyCanvas();
58
59 // accessors for the frame
60 const wxFont& GetTextFont() const { return m_font; }
61 const wxColour& GetColour() const { return m_colour; }
62 void SetTextFont(const wxFont& font) { m_font = font; }
63 void SetColour(const wxColour& colour) { m_colour = colour; }
64
65 // event handlers
66 void OnPaint( wxPaintEvent &event );
67
68 private:
69 wxColour m_colour;
70 wxFont m_font;
71
72 DECLARE_EVENT_TABLE()
73 };
74
75 // Define a new frame type: this is going to be our main frame
76 class MyFrame : public wxFrame
77 {
78 public:
79 // ctor(s)
80 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
81
82 // accessors
83 MyCanvas *GetCanvas() const { return m_canvas; }
84
85 // event handlers (these functions should _not_ be virtual)
86 void OnQuit(wxCommandEvent& event);
87 void OnAbout(wxCommandEvent& event);
88 void OnIncFont(wxCommandEvent& event) { DoResizeFont(+2); }
89 void OnDecFont(wxCommandEvent& event) { DoResizeFont(-2); }
90
91 void OnViewMsg(wxCommandEvent& event);
92 void OnSelectFont(wxCommandEvent& event);
93 void OnEnumerateFamiliesForEncoding(wxCommandEvent& event);
94 void OnEnumerateFamilies(wxCommandEvent& WXUNUSED(event))
95 { DoEnumerateFamilies(FALSE); }
96 void OnEnumerateFixedFamilies(wxCommandEvent& WXUNUSED(event))
97 { DoEnumerateFamilies(TRUE); }
98 void OnEnumerateEncodings(wxCommandEvent& event);
99
100 void OnCheckNativeToFromString(wxCommandEvent& event);
101
102 protected:
103 bool DoEnumerateFamilies(bool fixedWidthOnly,
104 wxFontEncoding encoding = wxFONTENCODING_SYSTEM,
105 bool silent = FALSE);
106
107 void DoResizeFont(int diff);
108 void DoChangeFont(const wxFont& font, const wxColour& col = wxNullColour);
109
110 size_t m_fontSize; // in points
111
112 wxTextCtrl *m_textctrl;
113 MyCanvas *m_canvas;
114
115 private:
116 // any class wishing to process wxWindows events must use this macro
117 DECLARE_EVENT_TABLE()
118 };
119
120 // ----------------------------------------------------------------------------
121 // constants
122 // ----------------------------------------------------------------------------
123
124 // IDs for the controls and the menu commands
125 enum
126 {
127 // menu items
128 Font_Quit = 1,
129 Font_About,
130 Font_ViewMsg,
131 Font_IncSize,
132 Font_DecSize,
133 Font_Choose = 100,
134 Font_EnumFamiliesForEncoding,
135 Font_EnumFamilies,
136 Font_EnumFixedFamilies,
137 Font_EnumEncodings,
138 Font_CheckNativeToFromString,
139 Font_Max
140 };
141
142 // ----------------------------------------------------------------------------
143 // event tables and other macros for wxWindows
144 // ----------------------------------------------------------------------------
145
146 // the event tables connect the wxWindows events with the functions (event
147 // handlers) which process them. It can be also done at run-time, but for the
148 // simple menu events like this the static method is much simpler.
149 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
150 EVT_MENU(Font_Quit, MyFrame::OnQuit)
151 EVT_MENU(Font_About, MyFrame::OnAbout)
152 EVT_MENU(Font_IncSize, MyFrame::OnIncFont)
153 EVT_MENU(Font_DecSize, MyFrame::OnDecFont)
154 EVT_MENU(Font_ViewMsg, MyFrame::OnViewMsg)
155 EVT_MENU(Font_Choose, MyFrame::OnSelectFont)
156 EVT_MENU(Font_EnumFamiliesForEncoding, MyFrame::OnEnumerateFamiliesForEncoding)
157 EVT_MENU(Font_EnumFamilies, MyFrame::OnEnumerateFamilies)
158 EVT_MENU(Font_EnumFixedFamilies, MyFrame::OnEnumerateFixedFamilies)
159 EVT_MENU(Font_EnumEncodings, MyFrame::OnEnumerateEncodings)
160 EVT_MENU(Font_CheckNativeToFromString, MyFrame::OnCheckNativeToFromString)
161 END_EVENT_TABLE()
162
163 // Create a new application object: this macro will allow wxWindows to create
164 // the application object during program execution (it's better than using a
165 // static object for many reasons) and also declares the accessor function
166 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
167 // not wxApp)
168 IMPLEMENT_APP(MyApp)
169
170 // ============================================================================
171 // implementation
172 // ============================================================================
173
174 // ----------------------------------------------------------------------------
175 // the application class
176 // ----------------------------------------------------------------------------
177
178 // `Main program' equivalent: the program execution "starts" here
179 bool MyApp::OnInit()
180 {
181 // Create the main application window
182 MyFrame *frame = new MyFrame("Font wxWindows demo",
183 wxPoint(50, 50), wxSize(450, 340));
184
185 // Show it and tell the application that it's our main window
186 frame->Show(TRUE);
187 SetTopWindow(frame);
188
189 // success: wxApp::OnRun() will be called which will enter the main message
190 // loop and the application will run. If we returned FALSE here, the
191 // application would exit immediately.
192 return TRUE;
193 }
194
195 // ----------------------------------------------------------------------------
196 // main frame
197 // ----------------------------------------------------------------------------
198
199 // frame constructor
200 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
201 : wxFrame((wxFrame *)NULL, -1, title, pos, size), m_textctrl(NULL)
202 {
203 m_fontSize = 12;
204
205 // create a menu bar
206 wxMenu *menuFile = new wxMenu;
207
208 menuFile->Append(Font_ViewMsg, "&View...\tCtrl-V",
209 "View an email message file");
210 menuFile->AppendSeparator();
211 menuFile->Append(Font_About, "&About...\tCtrl-A", "Show about dialog");
212 menuFile->AppendSeparator();
213 menuFile->Append(Font_Quit, "E&xit\tAlt-X", "Quit this program");
214
215 wxMenu *menuFont = new wxMenu;
216 menuFont->Append(Font_IncSize, "&Increase font size by 2 points\tCtrl-I");
217 menuFont->Append(Font_DecSize, "&Decrease font size by 2 points\tCtrl-D");
218 menuFont->AppendSeparator();
219 menuFont->Append(Font_Choose, "&Select font...\tCtrl-S",
220 "Select a standard font");
221 menuFont->AppendSeparator();
222 menuFont->Append(Font_EnumFamilies, "Enumerate font &families\tCtrl-F");
223 menuFont->Append(Font_EnumFixedFamilies,
224 "Enumerate fi&xed font families\tCtrl-X");
225 menuFont->Append(Font_EnumEncodings,
226 "Enumerate &encodings\tCtrl-E");
227 menuFont->Append(Font_EnumFamiliesForEncoding,
228 "Find font for en&coding...\tCtrl-C",
229 "Find font families for given encoding");
230 menuFont->AppendSeparator();
231 menuFont->Append(Font_CheckNativeToFromString,
232 "Check Native Font Info To/From String");
233
234 // now append the freshly created menu to the menu bar...
235 wxMenuBar *menuBar = new wxMenuBar;
236 menuBar->Append(menuFile, "&File");
237 menuBar->Append(menuFont, "F&ont");
238
239 // ... and attach this menu bar to the frame
240 SetMenuBar(menuBar);
241
242 wxSplitterWindow *splitter = new wxSplitterWindow(this);
243
244 m_textctrl = new wxTextCtrl(splitter, -1,
245 "Paste text here to see how it looks\n"
246 "like in the given font",
247 wxDefaultPosition, wxDefaultSize,
248 wxTE_MULTILINE);
249
250 m_canvas = new MyCanvas(splitter);
251
252 splitter->SplitHorizontally(m_textctrl, m_canvas, 100);
253
254 // create a status bar just for fun (by default with 1 pane only)
255 CreateStatusBar();
256 SetStatusText("Welcome to wxWindows font demo!");
257 }
258
259 // --------------------------------------------------------
260
261 class MyEncodingEnumerator : public wxFontEnumerator
262 {
263 public:
264 MyEncodingEnumerator()
265 { m_n = 0; }
266
267 const wxString& GetText() const
268 { return m_text; }
269
270 protected:
271 virtual bool OnFontEncoding(const wxString& facename,
272 const wxString& encoding)
273 {
274 wxString text;
275 text.Printf(wxT("Encoding %d: %s (available in facename '%s')\n"),
276 ++m_n, encoding.c_str(), facename.c_str());
277 m_text += text;
278 return TRUE;
279 }
280
281 private:
282 size_t m_n;
283 wxString m_text;
284 };
285
286 void MyFrame::OnEnumerateEncodings(wxCommandEvent& WXUNUSED(event))
287 {
288 MyEncodingEnumerator fontEnumerator;
289
290 fontEnumerator.EnumerateEncodings();
291
292 wxLogMessage(wxT("Enumerating all available encodings:\n%s"),
293 fontEnumerator.GetText().c_str());
294 }
295
296 // -------------------------------------------------------------
297
298 class MyFontEnumerator : public wxFontEnumerator
299 {
300 public:
301 bool GotAny() const
302 { return !m_facenames.IsEmpty(); }
303
304 const wxArrayString& GetFacenames() const
305 { return m_facenames; }
306
307 protected:
308 virtual bool OnFacename(const wxString& facename)
309 {
310 m_facenames.Add(facename);
311 return TRUE;
312 }
313
314 private:
315 wxArrayString m_facenames;
316 } fontEnumerator;
317
318 bool MyFrame::DoEnumerateFamilies(bool fixedWidthOnly,
319 wxFontEncoding encoding,
320 bool silent)
321 {
322 MyFontEnumerator fontEnumerator;
323
324 fontEnumerator.EnumerateFacenames(encoding, fixedWidthOnly);
325
326 if ( fontEnumerator.GotAny() )
327 {
328 int nFacenames = fontEnumerator.GetFacenames().GetCount();
329 if ( !silent )
330 {
331 wxLogStatus(this, wxT("Found %d %sfonts"),
332 nFacenames, fixedWidthOnly ? wxT("fixed width ") : wxT(""));
333 }
334
335 wxString facename;
336 if ( silent )
337 {
338 // choose the first
339 facename = fontEnumerator.GetFacenames().Item(0);
340 }
341 else
342 {
343 // let the user choose
344 wxString *facenames = new wxString[nFacenames];
345 int n;
346 for ( n = 0; n < nFacenames; n++ )
347 facenames[n] = fontEnumerator.GetFacenames().Item(n);
348
349 n = wxGetSingleChoiceIndex("Choose a facename", "Font demo",
350 nFacenames, facenames, this);
351
352 if ( n != -1 )
353 facename = facenames[n];
354
355 delete [] facenames;
356 }
357
358 if ( !facename.IsEmpty() )
359 {
360 wxFont font(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
361 wxFONTWEIGHT_NORMAL, FALSE, facename, encoding);
362
363 DoChangeFont(font);
364 }
365
366 return TRUE;
367 }
368 else if ( !silent )
369 {
370 wxLogWarning(wxT("No such fonts found."));
371 }
372
373 return FALSE;
374 }
375
376 void MyFrame::OnEnumerateFamiliesForEncoding(wxCommandEvent& WXUNUSED(event))
377 {
378 static wxFontEncoding encodings[] =
379 {
380 wxFONTENCODING_ISO8859_1,
381 wxFONTENCODING_ISO8859_2,
382 wxFONTENCODING_ISO8859_5,
383 wxFONTENCODING_ISO8859_7,
384 wxFONTENCODING_ISO8859_15,
385 wxFONTENCODING_KOI8,
386 wxFONTENCODING_CP1250,
387 wxFONTENCODING_CP1251,
388 wxFONTENCODING_CP1252,
389 };
390
391 static const wxString encodingNames[] =
392 {
393 "Western European (ISO-8859-1)",
394 "Central European (ISO-8859-2)",
395 "Cyrillic (ISO-8859-5)",
396 "Greek (ISO-8859-7)",
397 "Western European with Euro (ISO-8859-15)",
398 "KOI8-R",
399 "Windows Central European (CP 1250)",
400 "Windows Cyrillic (CP 1251)",
401 "Windows Western European (CP 1252)",
402 };
403
404 int n = wxGetSingleChoiceIndex("Choose an encoding", "Font demo",
405 WXSIZEOF(encodingNames),
406 encodingNames,
407 this);
408
409 if ( n != -1 )
410 {
411 DoEnumerateFamilies(FALSE, encodings[n]);
412 }
413 }
414
415 void MyFrame::OnCheckNativeToFromString(wxCommandEvent& WXUNUSED(event))
416 {
417 wxString fontInfo = m_canvas->GetTextFont().GetNativeFontInfoDesc();
418
419 if ( fontInfo.IsEmpty() )
420 {
421 wxLogError(wxT("Native font info string is empty!"));
422 }
423 else
424 {
425 wxFont *font = wxFont::New(fontInfo);
426 if ( fontInfo != font->GetNativeFontInfoDesc() )
427 wxLogError(wxT("wxNativeFontInfo ToString()/FromString() broken!"));
428 else
429 wxLogMessage(wxT("wxNativeFontInfo works: %s"), fontInfo.c_str());
430
431 delete font;
432 }
433 }
434
435 void MyFrame::DoResizeFont(int diff)
436 {
437 wxFont font = m_canvas->GetTextFont();
438
439 font.SetPointSize(font.GetPointSize() + diff);
440 DoChangeFont(font);
441 }
442
443 void MyFrame::DoChangeFont(const wxFont& font, const wxColour& col)
444 {
445 m_canvas->SetTextFont(font);
446 if ( col.Ok() )
447 m_canvas->SetColour(col);
448 m_canvas->Refresh();
449
450 m_textctrl->SetFont(font);
451 if ( col.Ok() )
452 m_textctrl->SetForegroundColour(col);
453 }
454
455 void MyFrame::OnSelectFont(wxCommandEvent& WXUNUSED(event))
456 {
457 wxFontData data;
458 data.SetInitialFont(m_canvas->GetTextFont());
459 data.SetColour(m_canvas->GetColour());
460
461 wxFontDialog dialog(this, &data);
462 if ( dialog.ShowModal() == wxID_OK )
463 {
464 wxFontData retData = dialog.GetFontData();
465 wxFont font = retData.GetChosenFont();
466 wxColour colour = retData.GetColour();
467
468 DoChangeFont(font, colour);
469 }
470 }
471
472 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
473 {
474 // TRUE is to force the frame to close
475 Close(TRUE);
476 }
477
478 void MyFrame::OnViewMsg(wxCommandEvent& WXUNUSED(event))
479 {
480 // first, choose the file
481 static wxString s_dir, s_file;
482 wxFileDialog dialog(this, "Open an email message file",
483 s_dir, s_file);
484 if ( dialog.ShowModal() != wxID_OK )
485 return;
486
487 // save for the next time
488 s_dir = dialog.GetDirectory();
489 s_file = dialog.GetFilename();
490
491 wxString filename = dialog.GetPath();
492
493 // load it and search for Content-Type header
494 wxTextFile file(filename);
495 if ( !file.Open() )
496 return;
497
498 wxString charset;
499
500 static const char *prefix = "Content-Type: text/plain; charset=";
501 const size_t len = strlen(prefix);
502
503 size_t n, count = file.GetLineCount();
504 for ( n = 0; n < count; n++ )
505 {
506 wxString line = file[n];
507
508 if ( !line )
509 {
510 // if it is an email message, headers are over, no need to parse
511 // all the file
512 break;
513 }
514
515 if ( line.Left(len) == prefix )
516 {
517 // found!
518 const wxChar *pc = line.c_str() + len;
519 if ( *pc == '"' )
520 pc++;
521
522 while ( *pc && *pc != '"' )
523 {
524 charset += *pc++;
525 }
526
527 break;
528 }
529 }
530
531 if ( !charset )
532 {
533 wxLogError(wxT("The file '%s' doesn't contain charset information."),
534 filename.c_str());
535
536 return;
537 }
538
539 // ok, now get the corresponding encoding
540 wxFontEncoding fontenc = wxTheFontMapper->CharsetToEncoding(charset);
541 if ( fontenc == wxFONTENCODING_SYSTEM )
542 {
543 wxLogError(wxT("Charset '%s' is unsupported."), charset.c_str());
544 return;
545 }
546
547 m_textctrl->LoadFile(filename);
548
549 if ( fontenc == wxFONTENCODING_UTF8 ||
550 !wxTheFontMapper->IsEncodingAvailable(fontenc) )
551 {
552 // try to find some similar encoding:
553 wxFontEncoding encAlt;
554 if ( wxTheFontMapper->GetAltForEncoding(fontenc, &encAlt) )
555 {
556 wxEncodingConverter conv;
557
558 if (conv.Init(fontenc, encAlt))
559 {
560 fontenc = encAlt;
561 m_textctrl -> SetValue(conv.Convert(m_textctrl -> GetValue()));
562 }
563 else
564 {
565 wxLogWarning(wxT("Cannot convert from '%s' to '%s'."),
566 wxFontMapper::GetEncodingDescription(fontenc).c_str(),
567 wxFontMapper::GetEncodingDescription(encAlt).c_str());
568 }
569 }
570 else
571 wxLogWarning(wxT("No fonts for encoding '%s' on this system."),
572 wxFontMapper::GetEncodingDescription(fontenc).c_str());
573 }
574
575 // and now create the correct font
576 if ( !DoEnumerateFamilies(FALSE, fontenc, TRUE /* silent */) )
577 {
578 wxFont font(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
579 wxFONTWEIGHT_NORMAL, FALSE /* !underlined */,
580 wxEmptyString /* facename */, fontenc);
581 if ( font.Ok() )
582 {
583 DoChangeFont(font);
584 }
585 else
586 {
587 wxLogWarning(wxT("No fonts for encoding '%s' on this system."),
588 wxFontMapper::GetEncodingDescription(fontenc).c_str());
589 }
590 }
591 }
592
593 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
594 {
595 wxMessageBox("wxWindows font demo\n"
596 "(c) 1999 Vadim Zeitlin",
597 "About Font",
598 wxOK | wxICON_INFORMATION, this);
599 }
600
601 // ----------------------------------------------------------------------------
602 // MyCanvas
603 // ----------------------------------------------------------------------------
604
605 BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
606 EVT_PAINT(MyCanvas::OnPaint)
607 END_EVENT_TABLE()
608
609 MyCanvas::MyCanvas( wxWindow *parent )
610 : wxWindow( parent, -1 ),
611 m_colour(*wxRED), m_font(*wxNORMAL_FONT)
612 {
613 }
614
615 MyCanvas::~MyCanvas()
616 {
617 }
618
619 void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
620 {
621 wxPaintDC dc(this);
622 PrepareDC(dc);
623
624 // set background
625 dc.SetBackground(wxBrush(wxT("white"), wxSOLID));
626 dc.Clear();
627
628 // output the font name/info
629 wxString fontInfo;
630 fontInfo.Printf(wxT("Font size is %d points, family is %s, encoding is '%s', style %s, weight %s"),
631 m_font.GetPointSize(),
632 m_font.GetFamilyString().c_str(),
633 wxTheFontMapper->
634 GetEncodingDescription(m_font.GetEncoding()).c_str(),
635 m_font.GetStyleString().c_str(),
636 m_font.GetWeightString().c_str());
637
638 dc.DrawText(fontInfo, 5, 5);
639
640 if ( m_font.Ok() )
641 {
642 wxString fontDesc = m_font.GetNativeFontInfoUserDesc();
643 fontInfo.Printf(wxT("Native font info: %s"), fontDesc.c_str());
644 dc.DrawText(fontInfo, 5, 5 + dc.GetCharHeight());
645 }
646
647 // the origin for our table
648 int x = 5,
649 y = dc.GetCharHeight() * (2 + 1);
650
651 // prepare to draw the font
652 dc.SetFont(m_font);
653 dc.SetTextForeground(m_colour);
654
655 // the size of one cell (Normally biggest char + small margin)
656 long maxCharWidth, maxCharHeight;
657 dc.GetTextExtent(wxT("W"), &maxCharWidth, &maxCharHeight);
658 int w = maxCharWidth + 5,
659 h = maxCharHeight + 4;
660
661
662 // print all font symbols from 32 to 256 in 7 rows of 32 chars each
663 for ( int i = 0; i < 7; i++ )
664 {
665 for ( int j = 0; j < 32; j++ )
666 {
667 wxChar c = 32 * (i + 1) + j;
668
669 long charWidth, charHeight;
670 dc.GetTextExtent(c, &charWidth, &charHeight);
671 dc.DrawText
672 (
673 c,
674 x + w*j + (maxCharWidth - charWidth) / 2 + 1,
675 y + h*i + (maxCharHeight - charHeight) / 2
676 );
677 }
678 }
679
680 // draw the lines between them
681 dc.SetPen(wxPen(wxColour("blue"), 1, wxSOLID));
682 int l;
683
684 // horizontal
685 for ( l = 0; l < 8; l++ )
686 {
687 int yl = y + h*l - 2;
688 dc.DrawLine(x - 2, yl, x + 32*w - 1, yl);
689 }
690
691 // and vertical
692 for ( l = 0; l < 33; l++ )
693 {
694 int xl = x + w*l - 2;
695 dc.DrawLine(xl, y - 2, xl, y + 7*h - 1);
696 }
697 }