2 * Copyright 2001-2010, Haiku.
3 * Distributed under the terms of the MIT License.
7 * DarkWyrm <bpmagic@columbus.rr.com>
8 * Axel Dörfler, axeld@pinc-software.de
9 * Philippe Saint-Pierre, stpere@gmail.com
10 * Stephan Aßmus <superstippi@gmx.de>
13 #include "FontSelectionView.h"
19 #include <MenuField.h>
21 #include <PopUpMenu.h>
23 #include <StringView.h>
24 #include <LayoutItem.h>
25 #include <GroupLayoutBuilder.h>
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "Font Selection view"
33 static const float kMinSize
= 8.0;
34 static const float kMaxSize
= 18.0;
36 static const int32 kMsgSetFamily
= 'fmly';
37 static const int32 kMsgSetStyle
= 'styl';
38 static const int32 kMsgSetSize
= 'size';
44 FontSelectionView::FontSelectionView(const char* name
, const char* label
,
45 bool separateStyles
, const BFont
* currentFont
)
51 if (currentFont
== NULL
)
52 fCurrentFont
= _DefaultFont();
54 fCurrentFont
= *currentFont
;
56 fSavedFont
= fCurrentFont
;
58 fSizesMenu
= new BPopUpMenu("size menu");
59 fFontsMenu
= new BPopUpMenu("font menu");
62 fFontsMenuField
= new BMenuField("fonts", label
, fFontsMenu
, B_WILL_DRAW
);
63 fFontsMenuField
->SetFont(be_bold_font
);
65 // styles menu, if desired
67 fStylesMenu
= new BPopUpMenu("styles menu");
68 fStylesMenuField
= new BMenuField("styles", B_TRANSLATE("Style:"),
69 fStylesMenu
, B_WILL_DRAW
);
72 fStylesMenuField
= NULL
;
76 fSizesMenuField
= new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu
,
78 fSizesMenuField
->SetAlignment(B_ALIGN_RIGHT
);
81 fPreviewText
= new BStringView("preview text",
82 B_TRANSLATE_COMMENT("The quick brown fox jumps over the lazy dog.",
83 "Don't translate this literally ! Use a phrase showing all "
84 "chars from A to Z."));
86 fPreviewText
->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED
,
88 fPreviewText
->SetHighUIColor(B_PANEL_BACKGROUND_COLOR
, 1.65);
89 fPreviewText
->SetAlignment(B_ALIGN_RIGHT
);
94 FontSelectionView::~FontSelectionView()
96 // Some controls may not have been attached...
97 if (!fPreviewText
->Window())
99 if (!fSizesMenuField
->Window())
100 delete fSizesMenuField
;
101 if (fStylesMenuField
&& !fStylesMenuField
->Window())
102 delete fStylesMenuField
;
103 if (!fFontsMenuField
->Window())
104 delete fFontsMenuField
;
111 FontSelectionView::AttachedToLooper()
119 FontSelectionView::MessageReceived(BMessage
* message
)
121 switch (message
->what
) {
125 if (message
->FindInt32("size", &size
) != B_OK
126 || size
== fCurrentFont
.Size())
129 fCurrentFont
.SetSize(size
);
130 _UpdateFontPreview();
138 if (message
->FindString("family", &family
) != B_OK
)
142 fCurrentFont
.GetFamilyAndStyle(NULL
, &style
);
144 BMenuItem
* familyItem
= fFontsMenu
->FindItem(family
);
145 if (familyItem
!= NULL
) {
146 _SelectCurrentFont(false);
148 BMenuItem
* styleItem
;
149 if (fStylesMenuField
!= NULL
)
150 styleItem
= fStylesMenuField
->Menu()->FindMarked();
152 styleItem
= familyItem
->Submenu()->FindItem(style
);
153 if (styleItem
== NULL
)
154 styleItem
= familyItem
->Submenu()->ItemAt(0);
157 if (styleItem
!= NULL
) {
158 styleItem
->SetMarked(true);
159 fCurrentFont
.SetFamilyAndStyle(family
, styleItem
->Label());
160 _UpdateFontPreview();
162 if (fStylesMenuField
!= NULL
)
163 _AddStylesToMenu(fCurrentFont
, fStylesMenuField
->Menu());
174 if (message
->FindString("family", &family
) != B_OK
175 || message
->FindString("style", &style
) != B_OK
)
178 BMenuItem
*familyItem
= fFontsMenu
->FindItem(family
);
182 _SelectCurrentFont(false);
183 familyItem
->SetMarked(true);
185 fCurrentFont
.SetFamilyAndStyle(family
, style
);
186 _UpdateFontPreview();
192 BHandler::MessageReceived(message
);
198 FontSelectionView::SetMessage(BMessage
* message
)
206 FontSelectionView::SetTarget(BHandler
* target
)
216 FontSelectionView::SetFont(const BFont
& font
, float size
)
218 BFont
resizedFont(font
);
219 resizedFont
.SetSize(size
);
220 SetFont(resizedFont
);
225 FontSelectionView::SetFont(const BFont
& font
)
227 if (font
== fCurrentFont
&& font
== fSavedFont
)
230 _SelectCurrentFont(false);
231 fSavedFont
= fCurrentFont
= font
;
232 _UpdateFontPreview();
234 _SelectCurrentFont(true);
235 _SelectCurrentSize(true);
240 FontSelectionView::SetSize(float size
)
242 SetFont(fCurrentFont
, size
);
247 FontSelectionView::Font() const
254 FontSelectionView::SetDefaults()
256 BFont defaultFont
= _DefaultFont();
257 if (defaultFont
== fCurrentFont
)
260 _SelectCurrentFont(false);
262 fCurrentFont
= defaultFont
;
263 _UpdateFontPreview();
265 _SelectCurrentFont(true);
266 _SelectCurrentSize(true);
271 FontSelectionView::Revert()
276 _SelectCurrentFont(false);
278 fCurrentFont
= fSavedFont
;
279 _UpdateFontPreview();
281 _SelectCurrentFont(true);
282 _SelectCurrentSize(true);
287 FontSelectionView::IsDefaultable()
289 return fCurrentFont
!= _DefaultFont();
294 FontSelectionView::IsRevertable()
296 return fCurrentFont
!= fSavedFont
;
301 FontSelectionView::UpdateFontsMenu()
303 int32 numFamilies
= count_font_families();
305 fFontsMenu
->RemoveItems(0, fFontsMenu
->CountItems(), true);
307 BFont font
= fCurrentFont
;
309 font_family currentFamily
;
310 font_style currentStyle
;
311 font
.GetFamilyAndStyle(¤tFamily
, ¤tStyle
);
313 for (int32 i
= 0; i
< numFamilies
; i
++) {
316 if (get_font_family(i
, &family
, &flags
) != B_OK
)
319 // if we're setting the fixed font, we only want to show fixed fonts
320 if (!strcmp(Name(), "fixed") && (flags
& B_IS_FIXED
) == 0)
323 font
.SetFamilyAndFace(family
, B_REGULAR_FACE
);
325 BMessage
* message
= new BMessage(kMsgSetFamily
);
326 message
->AddString("family", family
);
327 message
->AddString("name", Name());
329 BMenuItem
* familyItem
;
330 if (fStylesMenuField
!= NULL
) {
331 familyItem
= new BMenuItem(family
, message
);
333 // Each family item has a submenu with all styles for that font.
334 BMenu
* stylesMenu
= new BMenu(family
);
335 _AddStylesToMenu(font
, stylesMenu
);
336 familyItem
= new BMenuItem(stylesMenu
, message
);
339 familyItem
->SetMarked(strcmp(family
, currentFamily
) == 0);
340 fFontsMenu
->AddItem(familyItem
);
341 familyItem
->SetTarget(this);
344 // Separate styles menu for only the current font.
345 if (fStylesMenuField
!= NULL
)
346 _AddStylesToMenu(fCurrentFont
, fStylesMenuField
->Menu());
350 // #pragma mark - private
354 FontSelectionView::CreateSizesLabelLayoutItem()
356 return fSizesMenuField
->CreateLabelLayoutItem();
361 FontSelectionView::CreateSizesMenuBarLayoutItem()
363 return fSizesMenuField
->CreateMenuBarLayoutItem();
368 FontSelectionView::CreateFontsLabelLayoutItem()
370 return fFontsMenuField
->CreateLabelLayoutItem();
375 FontSelectionView::CreateFontsMenuBarLayoutItem()
377 return fFontsMenuField
->CreateMenuBarLayoutItem();
382 FontSelectionView::CreateStylesLabelLayoutItem()
384 if (fStylesMenuField
)
385 return fStylesMenuField
->CreateLabelLayoutItem();
391 FontSelectionView::CreateStylesMenuBarLayoutItem()
393 if (fStylesMenuField
)
394 return fStylesMenuField
->CreateMenuBarLayoutItem();
400 FontSelectionView::PreviewBox() const
406 // #pragma mark - private
410 FontSelectionView::_Invoke()
412 if (fTarget
!= NULL
&& fTarget
->Looper() != NULL
&& fMessage
!= NULL
) {
413 BMessage
message(*fMessage
);
414 fTarget
->Looper()->PostMessage(&message
, fTarget
);
420 FontSelectionView::_DefaultFont() const
422 if (strcmp(Name(), "bold") == 0)
423 return *be_bold_font
;
424 if (strcmp(Name(), "fixed") == 0)
425 return *be_fixed_font
;
427 return *be_plain_font
;
432 FontSelectionView::_SelectCurrentFont(bool select
)
436 fCurrentFont
.GetFamilyAndStyle(&family
, &style
);
438 BMenuItem
*item
= fFontsMenu
->FindItem(family
);
440 item
->SetMarked(select
);
442 if (item
->Submenu() != NULL
) {
443 item
= item
->Submenu()->FindItem(style
);
445 item
->SetMarked(select
);
452 FontSelectionView::_SelectCurrentSize(bool select
)
455 snprintf(label
, sizeof(label
), "%" B_PRId32
, (int32
)fCurrentFont
.Size());
457 BMenuItem
* item
= fSizesMenu
->FindItem(label
);
459 item
->SetMarked(select
);
464 FontSelectionView::_UpdateFontPreview()
466 fPreviewText
->SetFont(&fCurrentFont
);
471 FontSelectionView::_BuildSizesMenu()
473 const int32 sizes
[] = {7, 8, 9, 10, 11, 12, 13, 14, 18, 21, 24, 0};
476 for (int32 i
= 0; sizes
[i
]; i
++) {
477 int32 size
= sizes
[i
];
478 if (size
< kMinSize
|| size
> kMaxSize
)
482 snprintf(label
, sizeof(label
), "%" B_PRId32
, size
);
484 BMessage
* message
= new BMessage(kMsgSetSize
);
485 message
->AddInt32("size", size
);
486 message
->AddString("name", Name());
488 BMenuItem
* item
= new BMenuItem(label
, message
);
489 if (size
== fCurrentFont
.Size())
490 item
->SetMarked(true);
492 fSizesMenu
->AddItem(item
);
493 item
->SetTarget(this);
499 FontSelectionView::_AddStylesToMenu(const BFont
& font
, BMenu
* stylesMenu
) const
501 stylesMenu
->RemoveItems(0, stylesMenu
->CountItems(), true);
502 stylesMenu
->SetRadioMode(true);
506 font
.GetFamilyAndStyle(&family
, &style
);
507 BString
currentStyle(style
);
509 int32 numStyles
= count_font_styles(family
);
511 for (int32 j
= 0; j
< numStyles
; j
++) {
512 if (get_font_style(family
, j
, &style
) != B_OK
)
515 BMessage
* message
= new BMessage(kMsgSetStyle
);
516 message
->AddString("family", (char*)family
);
517 message
->AddString("style", (char*)style
);
519 BMenuItem
* item
= new BMenuItem(style
, message
);
520 item
->SetMarked(currentStyle
== style
);
522 stylesMenu
->AddItem(item
);
523 item
->SetTarget(this);