repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / preferences / appearance / FontSelectionView.cpp
blobeaae7b4d8358b1872c24e11df1369b7c4330f179
1 /*
2 * Copyright 2001-2015, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Mark Hogben
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>
14 #include "FontSelectionView.h"
16 #include <Box.h>
17 #include <Catalog.h>
18 #include <Locale.h>
19 #include <MenuField.h>
20 #include <MenuItem.h>
21 #include <PopUpMenu.h>
22 #include <String.h>
23 #include <StringView.h>
24 #include <LayoutItem.h>
25 #include <GroupLayoutBuilder.h>
27 #include <stdio.h>
30 #undef B_TRANSLATION_CONTEXT
31 #define B_TRANSLATION_CONTEXT "Font Selection view"
34 #define INSTANT_UPDATE
35 // if defined, the system font will be updated immediately, and not
36 // only on exit
38 static const float kMinSize = 8.0;
39 static const float kMaxSize = 24.0;
42 // private font API
43 extern void _set_system_font_(const char *which, font_family family,
44 font_style style, float size);
45 extern status_t _get_system_default_font_(const char* which,
46 font_family family, font_style style, float* _size);
49 #ifdef B_BEOS_VERSION_DANO
50 // this call only exists under R5
51 void
52 _set_system_font_(const char *which, font_family family,
53 font_style style, float size)
55 puts("you don't have _set_system_font_()");
57 #endif
59 #if !defined(HAIKU_TARGET_PLATFORM_HAIKU) && !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
60 // this call only exists under Haiku (and the test environment)
61 status_t
62 _get_system_default_font_(const char* which, font_family family,
63 font_style style, float* _size)
65 puts("you don't have _get_system_default_font_()");
66 return B_ERROR;
68 #endif
71 // #pragma mark -
74 FontSelectionView::FontSelectionView(const char* name,
75 const char* label, const BFont* currentFont)
77 BView(name, B_WILL_DRAW),
78 fMessageTarget(this)
80 if (currentFont == NULL) {
81 if (!strcmp(Name(), "plain"))
82 fCurrentFont = *be_plain_font;
83 else if (!strcmp(Name(), "bold"))
84 fCurrentFont = *be_bold_font;
85 else if (!strcmp(Name(), "fixed"))
86 fCurrentFont = *be_fixed_font;
87 else if (!strcmp(Name(), "menu")) {
88 menu_info info;
89 get_menu_info(&info);
91 fCurrentFont.SetFamilyAndStyle(info.f_family, info.f_style);
92 fCurrentFont.SetSize(info.font_size);
94 } else
95 fCurrentFont = *currentFont;
97 fSavedFont = fCurrentFont;
99 fSizesMenu = new BPopUpMenu("size menu");
100 _BuildSizesMenu();
102 fFontsMenu = new BPopUpMenu("font menu");
104 // font menu
105 fFontsMenuField = new BMenuField("fonts", label, fFontsMenu);
106 fFontsMenuField->SetAlignment(B_ALIGN_RIGHT);
108 // size menu
109 fSizesMenuField = new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu);
110 fSizesMenuField->SetAlignment(B_ALIGN_RIGHT);
112 // preview
113 fPreviewText = new BStringView("preview text",
114 B_TRANSLATE_COMMENT("The quick brown fox jumps over the lazy dog.",
115 "Don't translate this literally ! Use a phrase showing all chars "
116 "from A to Z."));
118 fPreviewText->SetFont(&fCurrentFont);
119 fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
121 // box around preview
122 fPreviewBox = new BBox("preview box", B_WILL_DRAW | B_FRAME_EVENTS);
123 fPreviewBox->AddChild(BGroupLayoutBuilder(B_HORIZONTAL)
124 .Add(fPreviewText)
125 .SetInsets(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING,
126 B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
127 .TopView()
132 FontSelectionView::~FontSelectionView()
134 #ifndef INSTANT_UPDATE
135 _UpdateSystemFont();
136 #endif
140 void
141 FontSelectionView::SetTarget(BHandler* messageTarget)
143 fMessageTarget = messageTarget;
144 fSizesMenu->SetTargetForItems(fMessageTarget);
148 BView*
149 FontSelectionView::GetPreviewBox()
151 return fPreviewBox;
155 void
156 FontSelectionView::MessageReceived(BMessage *msg)
158 switch (msg->what) {
159 case kMsgSetSize:
161 int32 size;
162 if (msg->FindInt32("size", &size) != B_OK
163 || size == fCurrentFont.Size())
164 break;
166 fCurrentFont.SetSize(size);
167 _UpdateFontPreview();
168 break;
171 case kMsgSetFamily:
173 const char* family;
174 if (msg->FindString("family", &family) != B_OK)
175 break;
177 font_style style;
178 fCurrentFont.GetFamilyAndStyle(NULL, &style);
180 BMenuItem *familyItem = fFontsMenu->FindItem(family);
181 if (familyItem != NULL) {
182 _SelectCurrentFont(false);
184 BMenuItem *item = familyItem->Submenu()->FindItem(style);
185 if (item == NULL)
186 item = familyItem->Submenu()->ItemAt(0);
188 if (item != NULL) {
189 item->SetMarked(true);
190 fCurrentFont.SetFamilyAndStyle(family, item->Label());
191 _UpdateFontPreview();
194 break;
197 case kMsgSetStyle:
199 const char* family;
200 const char* style;
201 if (msg->FindString("family", &family) != B_OK
202 || msg->FindString("style", &style) != B_OK)
203 break;
205 BMenuItem *familyItem = fFontsMenu->FindItem(family);
206 if (!familyItem)
207 break;
209 _SelectCurrentFont(false);
210 familyItem->SetMarked(true);
212 fCurrentFont.SetFamilyAndStyle(family, style);
213 _UpdateFontPreview();
214 break;
217 default:
218 BView::MessageReceived(msg);
223 BLayoutItem*
224 FontSelectionView::CreateSizesLabelLayoutItem()
226 return fSizesMenuField->CreateLabelLayoutItem();
230 BLayoutItem*
231 FontSelectionView::CreateSizesMenuBarLayoutItem()
233 return fSizesMenuField->CreateMenuBarLayoutItem();
237 BLayoutItem*
238 FontSelectionView::CreateFontsLabelLayoutItem()
240 return fFontsMenuField->CreateLabelLayoutItem();
244 BLayoutItem*
245 FontSelectionView::CreateFontsMenuBarLayoutItem()
247 return fFontsMenuField->CreateMenuBarLayoutItem();
251 void
252 FontSelectionView::_BuildSizesMenu()
254 const int32 sizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20,
255 21, 24, 0};
257 // build size menu
258 for (int32 i = 0; sizes[i]; i++) {
259 int32 size = sizes[i];
260 if (size < kMinSize || size > kMaxSize)
261 continue;
263 char label[32];
264 snprintf(label, sizeof(label), "%" B_PRId32, size);
266 BMessage* message = new BMessage(kMsgSetSize);
267 message->AddInt32("size", size);
268 message->AddString("name", Name());
270 BMenuItem* item = new BMenuItem(label, message);
271 if (size == fCurrentFont.Size())
272 item->SetMarked(true);
274 fSizesMenu->AddItem(item);
279 void
280 FontSelectionView::_SelectCurrentFont(bool select)
282 font_family family;
283 font_style style;
284 fCurrentFont.GetFamilyAndStyle(&family, &style);
286 BMenuItem *item = fFontsMenu->FindItem(family);
287 if (item != NULL) {
288 item->SetMarked(select);
290 if (item->Submenu() != NULL) {
291 item = item->Submenu()->FindItem(style);
292 if (item != NULL)
293 item->SetMarked(select);
299 void
300 FontSelectionView::_SelectCurrentSize(bool select)
302 char label[16];
303 snprintf(label, sizeof(label), "%" B_PRId32, (int32)fCurrentFont.Size());
305 BMenuItem* item = fSizesMenu->FindItem(label);
306 if (item != NULL)
307 item->SetMarked(select);
311 void
312 FontSelectionView::_UpdateFontPreview()
314 fPreviewText->SetFont(&fCurrentFont);
316 #ifdef INSTANT_UPDATE
317 _UpdateSystemFont();
318 #endif
322 void
323 FontSelectionView::_UpdateSystemFont()
325 font_family family;
326 font_style style;
327 fCurrentFont.GetFamilyAndStyle(&family, &style);
329 if (strcmp(Name(), "menu") == 0) {
330 // The menu font is not handled as a system font
331 menu_info info;
332 get_menu_info(&info);
334 strlcpy(info.f_family, (const char*)family, B_FONT_FAMILY_LENGTH);
335 strlcpy(info.f_style, (const char*)style, B_FONT_STYLE_LENGTH);
336 info.font_size = fCurrentFont.Size();
338 set_menu_info(&info);
339 } else
340 _set_system_font_(Name(), family, style, fCurrentFont.Size());
344 void
345 FontSelectionView::SetDefaults()
347 font_family family;
348 font_style style;
349 float size;
350 const char* fontName;
352 if (strcmp(Name(), "menu") == 0)
353 fontName = "plain";
354 else
355 fontName = Name();
357 if (_get_system_default_font_(fontName, family, style, &size) != B_OK) {
358 Revert();
359 return;
362 BFont defaultFont;
363 defaultFont.SetFamilyAndStyle(family, style);
364 defaultFont.SetSize(size);
366 if (defaultFont == fCurrentFont)
367 return;
369 _SelectCurrentFont(false);
371 fCurrentFont = defaultFont;
372 _UpdateFontPreview();
374 _SelectCurrentFont(true);
375 _SelectCurrentSize(true);
379 void
380 FontSelectionView::Revert()
382 if (!IsRevertable())
383 return;
385 _SelectCurrentFont(false);
387 fCurrentFont = fSavedFont;
388 _UpdateFontPreview();
390 _SelectCurrentFont(true);
391 _SelectCurrentSize(true);
395 bool
396 FontSelectionView::IsDefaultable()
398 font_family defaultFamily;
399 font_style defaultStyle;
400 float defaultSize;
401 const char* fontName;
403 if (strcmp(Name(), "menu") == 0)
404 fontName = "plain";
405 else
406 fontName = Name();
408 if (_get_system_default_font_(fontName, defaultFamily, defaultStyle,
409 &defaultSize) != B_OK) {
410 return false;
413 font_family currentFamily;
414 font_style currentStyle;
415 float currentSize;
417 fCurrentFont.GetFamilyAndStyle(&currentFamily, &currentStyle);
418 currentSize = fCurrentFont.Size();
420 return strcmp(currentFamily, defaultFamily) != 0
421 || strcmp(currentStyle, defaultStyle) != 0
422 || currentSize != defaultSize;
426 bool
427 FontSelectionView::IsRevertable()
429 return fCurrentFont != fSavedFont;
433 void
434 FontSelectionView::UpdateFontsMenu()
436 int32 numFamilies = count_font_families();
438 fFontsMenu->RemoveItems(0, fFontsMenu->CountItems(), true);
439 BFont font;
440 fFontsMenu->GetFont(&font);
442 font_family currentFamily;
443 font_style currentStyle;
444 fCurrentFont.GetFamilyAndStyle(&currentFamily, &currentStyle);
446 for (int32 i = 0; i < numFamilies; i++) {
447 font_family family;
448 uint32 flags;
449 if (get_font_family(i, &family, &flags) != B_OK)
450 continue;
452 // if we're setting the fixed font, we only want to show fixed fonts
453 if (!strcmp(Name(), "fixed") && (flags & B_IS_FIXED) == 0)
454 continue;
456 float width = font.StringWidth(family);
457 if (width > fMaxFontNameWidth)
458 fMaxFontNameWidth = width;
460 BMenu* stylesMenu = new BMenu(family);
461 stylesMenu->SetRadioMode(true);
462 stylesMenu->SetFont(&font);
464 BMessage* message = new BMessage(kMsgSetFamily);
465 message->AddString("family", family);
466 message->AddString("name", Name());
468 BMenuItem* familyItem = new BMenuItem(stylesMenu, message);
469 fFontsMenu->AddItem(familyItem);
471 int32 numStyles = count_font_styles(family);
473 for (int32 j = 0; j < numStyles; j++) {
474 font_style style;
475 if (get_font_style(family, j, &style, &flags) != B_OK)
476 continue;
478 message = new BMessage(kMsgSetStyle);
479 message->AddString("family", (char*)family);
480 message->AddString("style", (char*)style);
481 message->AddString("name", Name());
483 BMenuItem *item = new BMenuItem(style, message);
485 if (!strcmp(style, currentStyle)
486 && !strcmp(family, currentFamily)) {
487 item->SetMarked(true);
488 familyItem->SetMarked(true);
490 stylesMenu->AddItem(item);
493 stylesMenu->SetTargetForItems(fMessageTarget);
496 fFontsMenu->SetTargetForItems(fMessageTarget);