Files
haiku-beta6/src/apps/terminal/AppearPrefView.cpp
T
Stefano Ceccherini e3b9a828db When building the font menu, also include font styles.
Now it's possible to select bold or oblique font styles.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33946 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-11-08 12:22:57 +00:00

302 lines
7.5 KiB
C++

/*
* Copyright 2001-2009, Haiku, Inc.
* Copyright 2003-2004 Kian Duffy, [email protected]
* Parts Copyright 1998-1999 Kazuho Okui and Takashi Murai.
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "AppearPrefView.h"
#include <stdio.h>
#include <stdlib.h>
#include <Button.h>
#include <Menu.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <PopUpMenu.h>
#include <TextControl.h>
#include <View.h>
#include "MenuUtil.h"
#include "PrefHandler.h"
#include "TermConst.h"
AppearancePrefView::AppearancePrefView(BRect frame, const char *name,
BMessenger messenger)
: PrefView(frame, name),
fAppearancePrefViewMessenger(messenger)
{
const char *color_tbl[] = {
PREF_TEXT_FORE_COLOR,
PREF_TEXT_BACK_COLOR,
PREF_CURSOR_FORE_COLOR,
PREF_CURSOR_BACK_COLOR,
PREF_SELECT_FORE_COLOR,
PREF_SELECT_BACK_COLOR,
#if 0
"",
PREF_IM_FORE_COLOR,
PREF_IM_BACK_COLOR,
PREF_IM_SELECT_COLOR,
"",
PREF_ANSI_BLACK_COLOR,
PREF_ANSI_RED_COLOR,
PREF_ANSI_GREEN_COLOR,
PREF_ANSI_YELLOW_COLOR,
PREF_ANSI_BLUE_COLOR,
PREF_ANSI_MAGENTA_COLOR,
PREF_ANSI_CYAN_COLOR,
PREF_ANSI_WHITE_COLOR,
#endif
NULL
};
float greenDividerSize = StringWidth("Green:") + 8.0;
float colorDividerSize = StringWidth("Color:") + 8.0;
BRect r(5, 5, 261, 25);
BMenu *menu = _MakeFontMenu(MSG_HALF_FONT_CHANGED,
PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY));
fFont = new BMenuField(r, "font", "Font:", menu);
fFont->SetDivider(colorDividerSize);
fFont->SetAlignment(B_ALIGN_RIGHT);
AddChild(fFont);
r.OffsetBy(r.Width() + 10, 0);
menu = _MakeSizeMenu(MSG_HALF_SIZE_CHANGED,
PrefHandler::Default()->getInt32(PREF_HALF_FONT_SIZE));
fFontSize = new BMenuField(r, "size", "Size:", menu);
fFontSize->SetDivider(greenDividerSize);
fFontSize->SetAlignment(B_ALIGN_RIGHT);
AddChild(fFontSize);
r.OffsetBy(-r.Width() - 10,r.Height() + 10);
fColorField = new BMenuField(r, "color", "Color:",
MakeMenu(MSG_COLOR_FIELD_CHANGED, color_tbl, color_tbl[0]));
fColorField->SetDivider(colorDividerSize);
fColorField->SetAlignment(B_ALIGN_RIGHT);
AddChild(fColorField);
fColorControl = SetupColorControl(BPoint(r.left, r.bottom + 10),
B_CELLS_32x8, 8.0, MSG_COLOR_CHANGED);
fColorControl->SetValue(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR));
BTextControl* redInput = (BTextControl*)fColorControl->ChildAt(0);
BTextControl* greenInput = (BTextControl*)fColorControl->ChildAt(1);
BTextControl* blueInput = (BTextControl*)fColorControl->ChildAt(2);
redInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
greenInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
blueInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
redInput->SetDivider(greenDividerSize);
greenInput->SetDivider(greenDividerSize);
blueInput->SetDivider(greenDividerSize);
}
void
AppearancePrefView::GetPreferredSize(float *_width, float *_height)
{
if (_width)
*_width = Bounds().Width();
if (*_height)
*_height = fColorControl->Frame().bottom;
}
void
AppearancePrefView::Revert()
{
fColorField->Menu()->ItemAt(0)->SetMarked(true);
fColorControl->SetValue(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR));
fFont->Menu()->FindItem(PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true);
fFontSize->Menu()->FindItem(PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true);
}
void
AppearancePrefView::AttachedToWindow()
{
fFontSize->Menu()->SetTargetForItems(this);
fFont->Menu()->SetTargetForItems(this);
fColorControl->SetTarget(this);
fColorField->Menu()->SetTargetForItems(this);
}
void
AppearancePrefView::MessageReceived(BMessage *msg)
{
bool modified = false;
switch (msg->what) {
case MSG_HALF_FONT_CHANGED:
{
const char *family = NULL;
const char *style = NULL;
msg->FindString("font_family", &family);
msg->FindString("font_style", &style);
PrefHandler *pref = PrefHandler::Default();
const char *currentFamily
= pref->getString(PREF_HALF_FONT_FAMILY);
const char *currentStyle
= pref->getString(PREF_HALF_FONT_STYLE);
if (currentFamily == NULL || strcmp(currentFamily, family)
|| currentStyle == NULL || strcmp(currentStyle, style)) {
pref->setString(PREF_HALF_FONT_FAMILY, family);
pref->setString(PREF_HALF_FONT_STYLE, style);
modified = true;
}
break;
}
case MSG_HALF_SIZE_CHANGED:
if (strcmp(PrefHandler::Default()->getString(PREF_HALF_FONT_SIZE),
fFontSize->Menu()->FindMarked()->Label())) {
PrefHandler::Default()->setString(PREF_HALF_FONT_SIZE,
fFontSize->Menu()->FindMarked()->Label());
modified = true;
}
break;
case MSG_COLOR_CHANGED: {
rgb_color oldColor = PrefHandler::Default()->getRGB(
fColorField->Menu()->FindMarked()->Label());
if (oldColor != fColorControl->ValueAsColor()) {
PrefHandler::Default()->setRGB(
fColorField->Menu()->FindMarked()->Label(),
fColorControl->ValueAsColor());
modified = true;
}
}
break;
case MSG_COLOR_FIELD_CHANGED:
fColorControl->SetValue(PrefHandler::Default()->getRGB(
fColorField->Menu()->FindMarked()->Label()));
break;
default:
PrefView::MessageReceived(msg);
return;
}
if (modified) {
fAppearancePrefViewMessenger.SendMessage(msg);
BMessenger messenger(this);
messenger.SendMessage(MSG_PREF_MODIFIED);
}
}
static bool
IsFontUsable(const BFont &font)
{
// TODO: If BFont::IsFullAndHalfFixed() was implemented, we could
// use that. But I don't think it's easily implementable using
// Freetype.
if (font.IsFixed())
return true;
// manually check if all applicable chars are the same width
char buffer[2] = { ' ', 0 };
int firstWidth = (int)ceilf(font.StringWidth(buffer));
for (int c = ' '+1; c <= 0x7e; c++) {
buffer[0] = c;
int width = (int)ceilf(font.StringWidth(buffer));
if (width != firstWidth)
return false;
}
return true;
}
BMenu *
AppearancePrefView::_MakeFontMenu(uint32 command, const char *defaultFontName)
{
BPopUpMenu *menu = new BPopUpMenu("");
int32 numFamilies = count_font_families();
uint32 flags;
for (int32 i = 0; i < numFamilies; i++) {
font_family family;
if (get_font_family(i, &family, &flags) == B_OK) {
BFont font;
font_style style;
int32 numStyles = count_font_styles(family);
for (int32 j = 0; j < numStyles; j++) {
if (get_font_style(family, j, &style) == B_OK) {
font.SetFamilyAndStyle(family, style);
if (IsFontUsable(font)) {
BMessage *message = new BMessage(command);
message->AddString("font_family", family);
message->AddString("font_style", style);
char itemLabel[134];
snprintf(itemLabel, sizeof(itemLabel),
"%s - %s", family, style);
BMenuItem *item = new BMenuItem(itemLabel,
message);
menu->AddItem(item);
if (!strcmp(defaultFontName, family))
item->SetMarked(true);
}
}
}
}
}
return menu;
}
BMenu *
AppearancePrefView::_MakeSizeMenu(uint32 command, uint8 defaultSize)
{
BPopUpMenu *menu = new BPopUpMenu("size");
int32 sizes[] = {9, 10, 11, 12, 14, 16, 18, 0};
bool found = false;
for (uint32 i = 0; sizes[i]; i++) {
BString string;
string << sizes[i];
BMenuItem *item = new BMenuItem(string.String(), new BMessage(command));
menu->AddItem(item);
if (sizes[i] == defaultSize) {
item->SetMarked(true);
found = true;
}
}
if (!found) {
for (uint32 i = 0; sizes[i]; i++) {
if (sizes[i] > defaultSize) {
BString string;
string << defaultSize;
BMenuItem *item = new BMenuItem(string.String(), new BMessage(command));
item->SetMarked(true);
menu->AddItem(item, i);
break;
}
}
}
return menu;
}