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 <TextControl.h> 20 #include <View.h> 21 22 #include "MenuUtil.h" 23 #include "PrefHandler.h" 24 #include "TermConst.h" 25 26 27 28 AppearancePrefView::AppearancePrefView(BRect frame, const char *name, 29 BMessenger messenger) 30 : PrefView(frame, name), 31 fAppearancePrefViewMessenger(messenger) 32 { 33 const char *color_tbl[] = { 34 PREF_TEXT_FORE_COLOR, 35 PREF_TEXT_BACK_COLOR, 36 PREF_CURSOR_FORE_COLOR, 37 PREF_CURSOR_BACK_COLOR, 38 PREF_SELECT_FORE_COLOR, 39 PREF_SELECT_BACK_COLOR, 40 #if 0 41 "", 42 PREF_IM_FORE_COLOR, 43 PREF_IM_BACK_COLOR, 44 PREF_IM_SELECT_COLOR, 45 "", 46 PREF_ANSI_BLACK_COLOR, 47 PREF_ANSI_RED_COLOR, 48 PREF_ANSI_GREEN_COLOR, 49 PREF_ANSI_YELLOW_COLOR, 50 PREF_ANSI_BLUE_COLOR, 51 PREF_ANSI_MAGENTA_COLOR, 52 PREF_ANSI_CYAN_COLOR, 53 PREF_ANSI_WHITE_COLOR, 54 #endif 55 NULL 56 }; 57 58 float greenDividerSize = StringWidth("Green:") + 8.0; 59 float colorDividerSize = StringWidth("Color:") + 8.0; 60 61 BRect r(5, 5, 261, 25); 62 63 BMenu *menu = _MakeFontMenu(MSG_HALF_FONT_CHANGED, 64 PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY)); 65 fFont = new BMenuField(r, "font", "Font:", menu); 66 fFont->SetDivider(colorDividerSize); 67 fFont->SetAlignment(B_ALIGN_RIGHT); 68 AddChild(fFont); 69 70 r.OffsetBy(r.Width() + 10, 0); 71 menu = _MakeSizeMenu(MSG_HALF_SIZE_CHANGED, 72 PrefHandler::Default()->getInt32(PREF_HALF_FONT_SIZE)); 73 fFontSize = new BMenuField(r, "size", "Size:", menu); 74 fFontSize->SetDivider(greenDividerSize); 75 fFontSize->SetAlignment(B_ALIGN_RIGHT); 76 AddChild(fFontSize); 77 78 r.OffsetBy(-r.Width() - 10,r.Height() + 10); 79 fColorField = new BMenuField(r, "color", "Color:", 80 MakeMenu(MSG_COLOR_FIELD_CHANGED, color_tbl, color_tbl[0])); 81 fColorField->SetDivider(colorDividerSize); 82 fColorField->SetAlignment(B_ALIGN_RIGHT); 83 AddChild(fColorField); 84 85 fColorControl = SetupColorControl(BPoint(r.left, r.bottom + 10), 86 B_CELLS_32x8, 8.0, MSG_COLOR_CHANGED); 87 fColorControl->SetValue(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR)); 88 89 BTextControl* redInput = (BTextControl*)fColorControl->ChildAt(0); 90 BTextControl* greenInput = (BTextControl*)fColorControl->ChildAt(1); 91 BTextControl* blueInput = (BTextControl*)fColorControl->ChildAt(2); 92 93 redInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 94 greenInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 95 blueInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 96 97 redInput->SetDivider(greenDividerSize); 98 greenInput->SetDivider(greenDividerSize); 99 blueInput->SetDivider(greenDividerSize); 100 } 101 102 103 void 104 AppearancePrefView::GetPreferredSize(float *_width, float *_height) 105 { 106 if (_width) 107 *_width = Bounds().Width(); 108 109 if (*_height) 110 *_height = fColorControl->Frame().bottom; 111 } 112 113 114 void 115 AppearancePrefView::Revert() 116 { 117 fColorField->Menu()->ItemAt(0)->SetMarked(true); 118 fColorControl->SetValue(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR)); 119 120 fFont->Menu()->FindItem(PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true); 121 fFontSize->Menu()->FindItem(PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true); 122 } 123 124 125 void 126 AppearancePrefView::AttachedToWindow() 127 { 128 fFontSize->Menu()->SetTargetForItems(this); 129 fFont->Menu()->SetTargetForItems(this); 130 131 fColorControl->SetTarget(this); 132 fColorField->Menu()->SetTargetForItems(this); 133 } 134 135 136 void 137 AppearancePrefView::MessageReceived(BMessage *msg) 138 { 139 bool modified = false; 140 141 switch (msg->what) { 142 case MSG_HALF_FONT_CHANGED: 143 if (strcmp( 144 PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY), 145 fFont->Menu()->FindMarked()->Label())) { 146 147 PrefHandler::Default()->setString(PREF_HALF_FONT_FAMILY, 148 fFont->Menu()->FindMarked()->Label()); 149 modified = true; 150 } 151 break; 152 153 case MSG_HALF_SIZE_CHANGED: 154 if (strcmp(PrefHandler::Default()->getString(PREF_HALF_FONT_SIZE), 155 fFontSize->Menu()->FindMarked()->Label())) { 156 157 PrefHandler::Default()->setString(PREF_HALF_FONT_SIZE, 158 fFontSize->Menu()->FindMarked()->Label()); 159 modified = true; 160 } 161 break; 162 163 case MSG_COLOR_CHANGED: { 164 rgb_color oldColor = PrefHandler::Default()->getRGB( 165 fColorField->Menu()->FindMarked()->Label()); 166 if (oldColor != fColorControl->ValueAsColor()) { 167 PrefHandler::Default()->setRGB( 168 fColorField->Menu()->FindMarked()->Label(), 169 fColorControl->ValueAsColor()); 170 modified = true; 171 } 172 } 173 break; 174 175 case MSG_COLOR_FIELD_CHANGED: 176 fColorControl->SetValue(PrefHandler::Default()->getRGB( 177 fColorField->Menu()->FindMarked()->Label())); 178 break; 179 180 default: 181 PrefView::MessageReceived(msg); 182 return; 183 } 184 185 if (modified) { 186 fAppearancePrefViewMessenger.SendMessage(msg); 187 188 BMessenger messenger(this); 189 messenger.SendMessage(MSG_PREF_MODIFIED); 190 } 191 } 192 193 194 static bool 195 IsFontUsable(const BFont &font) 196 { 197 // TODO: If BFont::IsFullAndHalfFixed() was implemented, we could 198 // use that. But I don't think it's easily implementable using 199 // Freetype. 200 201 if (font.IsFixed()) 202 return true; 203 204 // manually check if all applicable chars are the same width 205 char buffer[2] = { ' ', 0 }; 206 int firstWidth = (int)ceilf(font.StringWidth(buffer)); 207 208 for (int c = ' '+1; c <= 0x7e; c++) { 209 buffer[0] = c; 210 int width = (int)ceilf(font.StringWidth(buffer)); 211 212 if (width != firstWidth) 213 return false; 214 } 215 216 return true; 217 } 218 219 220 BMenu * 221 AppearancePrefView::_MakeFontMenu(uint32 command, const char *defaultFontName) 222 { 223 BPopUpMenu *menu = new BPopUpMenu(""); 224 int32 numFamilies = count_font_families(); 225 uint32 flags; 226 227 for (int32 i = 0; i < numFamilies; i++) { 228 font_family family; 229 if (get_font_family(i, &family, &flags) == B_OK) { 230 BFont font; 231 font.SetFamilyAndStyle(family, NULL); 232 if (IsFontUsable(font)) { 233 BMenuItem *item = new BMenuItem(family, new BMessage(command)); 234 menu->AddItem(item); 235 if (!strcmp(defaultFontName, family)) 236 item->SetMarked(true); 237 } 238 } 239 } 240 241 return menu; 242 } 243 244 245 BMenu * 246 AppearancePrefView::_MakeSizeMenu(uint32 command, uint8 defaultSize) 247 { 248 BPopUpMenu *menu = new BPopUpMenu("size"); 249 int32 sizes[] = {9, 10, 11, 12, 14, 16, 18, 0}; 250 251 bool found = false; 252 253 for (uint32 i = 0; sizes[i]; i++) { 254 BString string; 255 string << sizes[i]; 256 257 BMenuItem *item = new BMenuItem(string.String(), new BMessage(command)); 258 menu->AddItem(item); 259 260 if (sizes[i] == defaultSize) { 261 item->SetMarked(true); 262 found = true; 263 } 264 } 265 if (!found) { 266 for (uint32 i = 0; sizes[i]; i++) { 267 if (sizes[i] > defaultSize) { 268 BString string; 269 string << defaultSize; 270 BMenuItem *item = new BMenuItem(string.String(), new BMessage(command)); 271 item->SetMarked(true); 272 menu->AddItem(item, i); 273 break; 274 } 275 } 276 } 277 278 return menu; 279 } 280