1 /* 2 * Copyright 2001-2009, Haiku, Inc. 3 * Copyright 2003-2004 Kian Duffy, myob@users.sourceforge.net 4 * Parts Copyright 1998-1999 Kazuho Okui and Takashi Murai. 5 * All rights reserved. Distributed under the terms of the MIT license. 6 */ 7 8 9 #include "AppearPrefView.h" 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 14 #include <Button.h> 15 #include <Menu.h> 16 #include <MenuField.h> 17 #include <MenuItem.h> 18 #include <PopUpMenu.h> 19 #include <View.h> 20 21 #include "MenuUtil.h" 22 #include "PrefHandler.h" 23 #include "TermConst.h" 24 25 26 static bool 27 IsFontUsable(const BFont &font) 28 { 29 // TODO: If BFont::IsFullAndHalfFixed() was implemented, we could 30 // use that. But I don't think it's easily implementable using 31 // Freetype. 32 33 if (font.IsFixed()) 34 return true; 35 36 bool widthOk = true; 37 int lastWidth = 0; 38 char buffer[2] = {0, 0}; 39 for (int c = 0x20 ; c <= 0x7e; c++){ 40 buffer[0] = c; 41 42 int width = (int)ceilf(font.StringWidth(buffer)); 43 if (c > 0x20 && width != lastWidth) 44 widthOk = false; 45 lastWidth = width; 46 } 47 48 return widthOk; 49 } 50 51 52 AppearancePrefView::AppearancePrefView(BRect frame, const char *name, 53 BMessenger messenger) 54 : PrefView(frame, name), 55 fAppearancePrefViewMessenger(messenger) 56 { 57 const char *color_tbl[] = { 58 PREF_TEXT_FORE_COLOR, 59 PREF_TEXT_BACK_COLOR, 60 PREF_CURSOR_FORE_COLOR, 61 PREF_CURSOR_BACK_COLOR, 62 PREF_SELECT_FORE_COLOR, 63 PREF_SELECT_BACK_COLOR, 64 #if 0 65 "", 66 PREF_IM_FORE_COLOR, 67 PREF_IM_BACK_COLOR, 68 PREF_IM_SELECT_COLOR, 69 "", 70 PREF_ANSI_BLACK_COLOR, 71 PREF_ANSI_RED_COLOR, 72 PREF_ANSI_GREEN_COLOR, 73 PREF_ANSI_YELLOW_COLOR, 74 PREF_ANSI_BLUE_COLOR, 75 PREF_ANSI_MAGENTA_COLOR, 76 PREF_ANSI_CYAN_COLOR, 77 PREF_ANSI_WHITE_COLOR, 78 #endif 79 NULL 80 }; 81 82 float fontDividerSize = StringWidth("Font:") + 8.0; 83 float sizeDividerSize = StringWidth("Size:") + 8.0; 84 85 BRect r(5, 5, 225, 25); 86 87 BMenu *menu = _MakeFontMenu(MSG_HALF_FONT_CHANGED, 88 PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY)); 89 fFont = new BMenuField(r, "font", "Font:", menu); 90 fFont->SetDivider(fontDividerSize); 91 AddChild(fFont); 92 93 r.OffsetBy(r.Width() + 10, 0); 94 menu = _MakeSizeMenu(MSG_HALF_SIZE_CHANGED, 95 PrefHandler::Default()->getInt32(PREF_HALF_FONT_SIZE)); 96 fFontSize = new BMenuField(r, "size", "Size:", menu); 97 fFontSize->SetDivider(sizeDividerSize); 98 AddChild(fFontSize); 99 100 r.OffsetBy(-r.Width() - 10,r.Height() + 25); 101 fColorField = new BMenuField(r, "color", "Change:", 102 MakeMenu(MSG_COLOR_FIELD_CHANGED, color_tbl, color_tbl[0])); 103 fColorField->SetDivider(StringWidth(fColorField->Label()) + 8.0); 104 AddChild(fColorField); 105 106 fColorControl = SetupColorControl(BPoint(r.left, r.bottom + 10), 107 B_CELLS_32x8, 7.0, MSG_COLOR_CHANGED); 108 fColorControl->SetValue(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR)); 109 } 110 111 112 void 113 AppearancePrefView::GetPreferredSize(float *_width, float *_height) 114 { 115 if (_width) 116 *_width = Bounds().Width(); 117 118 if (*_height) 119 *_height = fColorControl->Frame().bottom; 120 } 121 122 123 void 124 AppearancePrefView::Revert() 125 { 126 fColorField->Menu()->ItemAt(0)->SetMarked(true); 127 fColorControl->SetValue(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR)); 128 129 fFont->Menu()->FindItem(PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true); 130 fFontSize->Menu()->FindItem(PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true); 131 } 132 133 134 void 135 AppearancePrefView::AttachedToWindow() 136 { 137 fFontSize->Menu()->SetTargetForItems(this); 138 fFont->Menu()->SetTargetForItems(this); 139 140 fColorControl->SetTarget(this); 141 fColorField->Menu()->SetTargetForItems(this); 142 } 143 144 145 void 146 AppearancePrefView::MessageReceived(BMessage *msg) 147 { 148 bool modified = false; 149 150 switch (msg->what) { 151 case MSG_HALF_FONT_CHANGED: 152 PrefHandler::Default()->setString(PREF_HALF_FONT_FAMILY, 153 fFont->Menu()->FindMarked()->Label()); 154 modified = true; 155 break; 156 157 case MSG_HALF_SIZE_CHANGED: 158 PrefHandler::Default()->setString(PREF_HALF_FONT_SIZE, 159 fFontSize->Menu()->FindMarked()->Label()); 160 modified = true; 161 break; 162 163 case MSG_COLOR_CHANGED: 164 PrefHandler::Default()->setRGB(fColorField->Menu()->FindMarked()->Label(), 165 fColorControl->ValueAsColor()); 166 modified = true; 167 break; 168 169 case MSG_COLOR_FIELD_CHANGED: 170 fColorControl->SetValue(PrefHandler::Default()->getRGB( 171 fColorField->Menu()->FindMarked()->Label())); 172 break; 173 174 default: 175 PrefView::MessageReceived(msg); 176 return; 177 } 178 179 if (modified) { 180 fAppearancePrefViewMessenger.SendMessage(msg); 181 182 BMessenger messenger(this); 183 messenger.SendMessage(MSG_PREF_MODIFIED); 184 } 185 } 186 187 188 BMenu * 189 AppearancePrefView::_MakeFontMenu(uint32 command, const char *defaultFontName) 190 { 191 BPopUpMenu *menu = new BPopUpMenu(""); 192 int32 numFamilies = count_font_families(); 193 194 for (int32 i = 0; i < numFamilies; i++) { 195 font_family family; 196 uint32 flags; 197 198 if (get_font_family(i, &family, &flags) == B_OK) { 199 BFont font; 200 font.SetFamilyAndStyle(family, NULL); 201 if (IsFontUsable(font)) { 202 BMenuItem *item = new BMenuItem(family, new BMessage(command)); 203 menu->AddItem(item); 204 if (!strcmp(defaultFontName, family)) 205 item->SetMarked(true); 206 } 207 } 208 } 209 210 return menu; 211 } 212 213 214 BMenu * 215 AppearancePrefView::_MakeSizeMenu(uint32 command, uint8 defaultSize) 216 { 217 BPopUpMenu *menu = new BPopUpMenu("size"); 218 int32 sizes[] = {9, 10, 11, 12, 14, 16, 18, 0}; 219 220 for (uint32 i = 0; sizes[i]; i++) { 221 BString string; 222 string << sizes[i]; 223 224 BMenuItem* item = new BMenuItem(string.String(), new BMessage(command)); 225 menu->AddItem(item); 226 227 if (sizes[i] == defaultSize) 228 item->SetMarked(true); 229 } 230 231 return menu; 232 } 233