xref: /haiku/src/apps/terminal/AppearPrefView.cpp (revision a1163de83ea633463a79de234b8742ee106531b2)
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