repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / webpositive / support / FontSelectionView.cpp
blob4d1c9ed2f5b09a76c4ea8b8c399d060f47dbaf87
1 /*
2 * Copyright 2001-2010, 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>
13 #include "FontSelectionView.h"
15 #include <Box.h>
16 #include <Catalog.h>
17 #include <Locale.h>
18 #include <Looper.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>
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';
41 // #pragma mark -
44 FontSelectionView::FontSelectionView(const char* name, const char* label,
45 bool separateStyles, const BFont* currentFont)
47 BHandler(name),
48 fMessage(NULL),
49 fTarget(NULL)
51 if (currentFont == NULL)
52 fCurrentFont = _DefaultFont();
53 else
54 fCurrentFont = *currentFont;
56 fSavedFont = fCurrentFont;
58 fSizesMenu = new BPopUpMenu("size menu");
59 fFontsMenu = new BPopUpMenu("font menu");
61 // font menu
62 fFontsMenuField = new BMenuField("fonts", label, fFontsMenu, B_WILL_DRAW);
63 fFontsMenuField->SetFont(be_bold_font);
65 // styles menu, if desired
66 if (separateStyles) {
67 fStylesMenu = new BPopUpMenu("styles menu");
68 fStylesMenuField = new BMenuField("styles", B_TRANSLATE("Style:"),
69 fStylesMenu, B_WILL_DRAW);
70 } else {
71 fStylesMenu = NULL;
72 fStylesMenuField = NULL;
75 // size menu
76 fSizesMenuField = new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu,
77 B_WILL_DRAW);
78 fSizesMenuField->SetAlignment(B_ALIGN_RIGHT);
80 // preview
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,
87 B_SIZE_UNLIMITED));
88 fPreviewText->SetHighUIColor(B_PANEL_BACKGROUND_COLOR, 1.65);
89 fPreviewText->SetAlignment(B_ALIGN_RIGHT);
90 _UpdateFontPreview();
94 FontSelectionView::~FontSelectionView()
96 // Some controls may not have been attached...
97 if (!fPreviewText->Window())
98 delete fPreviewText;
99 if (!fSizesMenuField->Window())
100 delete fSizesMenuField;
101 if (fStylesMenuField && !fStylesMenuField->Window())
102 delete fStylesMenuField;
103 if (!fFontsMenuField->Window())
104 delete fFontsMenuField;
106 delete fMessage;
110 void
111 FontSelectionView::AttachedToLooper()
113 _BuildSizesMenu();
114 UpdateFontsMenu();
118 void
119 FontSelectionView::MessageReceived(BMessage* message)
121 switch (message->what) {
122 case kMsgSetSize:
124 int32 size;
125 if (message->FindInt32("size", &size) != B_OK
126 || size == fCurrentFont.Size())
127 break;
129 fCurrentFont.SetSize(size);
130 _UpdateFontPreview();
131 _Invoke();
132 break;
135 case kMsgSetFamily:
137 const char* family;
138 if (message->FindString("family", &family) != B_OK)
139 break;
141 font_style style;
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();
151 else {
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());
166 _Invoke();
167 break;
170 case kMsgSetStyle:
172 const char* family;
173 const char* style;
174 if (message->FindString("family", &family) != B_OK
175 || message->FindString("style", &style) != B_OK)
176 break;
178 BMenuItem *familyItem = fFontsMenu->FindItem(family);
179 if (!familyItem)
180 break;
182 _SelectCurrentFont(false);
183 familyItem->SetMarked(true);
185 fCurrentFont.SetFamilyAndStyle(family, style);
186 _UpdateFontPreview();
187 _Invoke();
188 break;
191 default:
192 BHandler::MessageReceived(message);
197 void
198 FontSelectionView::SetMessage(BMessage* message)
200 delete fMessage;
201 fMessage = message;
205 void
206 FontSelectionView::SetTarget(BHandler* target)
208 fTarget = target;
212 // #pragma mark -
215 void
216 FontSelectionView::SetFont(const BFont& font, float size)
218 BFont resizedFont(font);
219 resizedFont.SetSize(size);
220 SetFont(resizedFont);
224 void
225 FontSelectionView::SetFont(const BFont& font)
227 if (font == fCurrentFont && font == fSavedFont)
228 return;
230 _SelectCurrentFont(false);
231 fSavedFont = fCurrentFont = font;
232 _UpdateFontPreview();
234 _SelectCurrentFont(true);
235 _SelectCurrentSize(true);
239 void
240 FontSelectionView::SetSize(float size)
242 SetFont(fCurrentFont, size);
246 const BFont&
247 FontSelectionView::Font() const
249 return fCurrentFont;
253 void
254 FontSelectionView::SetDefaults()
256 BFont defaultFont = _DefaultFont();
257 if (defaultFont == fCurrentFont)
258 return;
260 _SelectCurrentFont(false);
262 fCurrentFont = defaultFont;
263 _UpdateFontPreview();
265 _SelectCurrentFont(true);
266 _SelectCurrentSize(true);
270 void
271 FontSelectionView::Revert()
273 if (!IsRevertable())
274 return;
276 _SelectCurrentFont(false);
278 fCurrentFont = fSavedFont;
279 _UpdateFontPreview();
281 _SelectCurrentFont(true);
282 _SelectCurrentSize(true);
286 bool
287 FontSelectionView::IsDefaultable()
289 return fCurrentFont != _DefaultFont();
293 bool
294 FontSelectionView::IsRevertable()
296 return fCurrentFont != fSavedFont;
300 void
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(&currentFamily, &currentStyle);
313 for (int32 i = 0; i < numFamilies; i++) {
314 font_family family;
315 uint32 flags;
316 if (get_font_family(i, &family, &flags) != B_OK)
317 continue;
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)
321 continue;
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);
332 } else {
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
353 BLayoutItem*
354 FontSelectionView::CreateSizesLabelLayoutItem()
356 return fSizesMenuField->CreateLabelLayoutItem();
360 BLayoutItem*
361 FontSelectionView::CreateSizesMenuBarLayoutItem()
363 return fSizesMenuField->CreateMenuBarLayoutItem();
367 BLayoutItem*
368 FontSelectionView::CreateFontsLabelLayoutItem()
370 return fFontsMenuField->CreateLabelLayoutItem();
374 BLayoutItem*
375 FontSelectionView::CreateFontsMenuBarLayoutItem()
377 return fFontsMenuField->CreateMenuBarLayoutItem();
381 BLayoutItem*
382 FontSelectionView::CreateStylesLabelLayoutItem()
384 if (fStylesMenuField)
385 return fStylesMenuField->CreateLabelLayoutItem();
386 return NULL;
390 BLayoutItem*
391 FontSelectionView::CreateStylesMenuBarLayoutItem()
393 if (fStylesMenuField)
394 return fStylesMenuField->CreateMenuBarLayoutItem();
395 return NULL;
399 BView*
400 FontSelectionView::PreviewBox() const
402 return fPreviewText;
406 // #pragma mark - private
409 void
410 FontSelectionView::_Invoke()
412 if (fTarget != NULL && fTarget->Looper() != NULL && fMessage != NULL) {
413 BMessage message(*fMessage);
414 fTarget->Looper()->PostMessage(&message, fTarget);
419 BFont
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;
426 else
427 return *be_plain_font;
431 void
432 FontSelectionView::_SelectCurrentFont(bool select)
434 font_family family;
435 font_style style;
436 fCurrentFont.GetFamilyAndStyle(&family, &style);
438 BMenuItem *item = fFontsMenu->FindItem(family);
439 if (item != NULL) {
440 item->SetMarked(select);
442 if (item->Submenu() != NULL) {
443 item = item->Submenu()->FindItem(style);
444 if (item != NULL)
445 item->SetMarked(select);
451 void
452 FontSelectionView::_SelectCurrentSize(bool select)
454 char label[16];
455 snprintf(label, sizeof(label), "%" B_PRId32, (int32)fCurrentFont.Size());
457 BMenuItem* item = fSizesMenu->FindItem(label);
458 if (item != NULL)
459 item->SetMarked(select);
463 void
464 FontSelectionView::_UpdateFontPreview()
466 fPreviewText->SetFont(&fCurrentFont);
470 void
471 FontSelectionView::_BuildSizesMenu()
473 const int32 sizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 18, 21, 24, 0};
475 // build size menu
476 for (int32 i = 0; sizes[i]; i++) {
477 int32 size = sizes[i];
478 if (size < kMinSize || size > kMaxSize)
479 continue;
481 char label[32];
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);
498 void
499 FontSelectionView::_AddStylesToMenu(const BFont& font, BMenu* stylesMenu) const
501 stylesMenu->RemoveItems(0, stylesMenu->CountItems(), true);
502 stylesMenu->SetRadioMode(true);
504 font_family family;
505 font_style style;
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)
513 continue;
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);