2 * Copyright 2001-2015, 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.
9 #include "AppearPrefView.h"
16 #include <CharacterSet.h>
17 #include <CharacterSetRoster.h>
19 #include <ColorControl.h>
20 #include <LayoutBuilder.h>
23 #include <MenuField.h>
25 #include <PopUpMenu.h>
26 #include <TextControl.h>
31 #include "PrefHandler.h"
32 #include "TermConst.h"
33 #include "TermWindow.h"
36 #undef B_TRANSLATION_CONTEXT
37 #define B_TRANSLATION_CONTEXT "Terminal AppearancePrefView"
44 AppearancePrefView::AppearancePrefView(const char* name
,
45 const BMessenger
& messenger
)
47 BGroupView(name
, B_VERTICAL
, 5),
48 fTerminalMessenger(messenger
)
50 const char* kColorTable
[] = {
51 B_TRANSLATE_MARK("Text"),
52 B_TRANSLATE_MARK("Background"),
53 B_TRANSLATE_MARK("Cursor"),
54 B_TRANSLATE_MARK("Text under cursor"),
55 B_TRANSLATE_MARK("Selected text"),
56 B_TRANSLATE_MARK("Selected background"),
60 fBlinkCursor
= new BCheckBox(
61 B_TRANSLATE("Blinking cursor"),
62 new BMessage(MSG_BLINK_CURSOR_CHANGED
));
64 fAllowBold
= new BCheckBox(
65 B_TRANSLATE("Allow bold text"),
66 new BMessage(MSG_ALLOW_BOLD_CHANGED
));
68 fWarnOnExit
= new BCheckBox(
69 B_TRANSLATE("Confirm exit if active programs exist"),
70 new BMessage(MSG_WARN_ON_EXIT_CHANGED
));
72 BMenu
* fontMenu
= _MakeFontMenu(MSG_HALF_FONT_CHANGED
,
73 PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY
),
74 PrefHandler::Default()->getString(PREF_HALF_FONT_STYLE
));
75 fFontField
= new BMenuField(B_TRANSLATE("Font:"), fontMenu
);
77 BMenu
* sizeMenu
= new (std::nothrow
) BPopUpMenu(
78 B_TRANSLATE_COMMENT("Custom", "Window size"));
79 if (sizeMenu
!= NULL
) {
80 TermWindow::MakeWindowSizeMenu(sizeMenu
);
81 sizeMenu
->SetLabelFromMarked(true);
83 fWindowSizeField
= new BMenuField(B_TRANSLATE("Window size:"), sizeMenu
);
85 BMenu
* encodingMenu
= new (std::nothrow
) BPopUpMenu("Text encoding");
86 if (encodingMenu
!= NULL
) {
87 TermWindow::MakeEncodingMenu(encodingMenu
);
88 encodingMenu
->SetLabelFromMarked(true);
90 fEncodingField
= new BMenuField(B_TRANSLATE("Encoding:"), encodingMenu
);
92 BPopUpMenu
* schemesPopUp
= _MakeColorSchemeMenu(MSG_COLOR_SCHEME_CHANGED
,
93 gPredefinedColorSchemes
, gPredefinedColorSchemes
[0]);
94 fColorSchemeField
= new BMenuField(B_TRANSLATE("Color scheme:"),
97 BPopUpMenu
* colorsPopUp
= _MakeMenu(MSG_COLOR_FIELD_CHANGED
, kColorTable
,
100 fColorField
= new BMenuField(B_TRANSLATE("Color:"), colorsPopUp
);
102 fTabTitle
= new BTextControl("tabTitle", B_TRANSLATE("Tab title:"), "",
104 fTabTitle
->SetModificationMessage(
105 new BMessage(MSG_TAB_TITLE_SETTING_CHANGED
));
106 fTabTitle
->SetToolTip(BString(B_TRANSLATE(
107 "The pattern specifying the tab titles. The following placeholders\n"
108 "can be used:")) << "\n" << kTooTipSetTabTitlePlaceholders
109 << "\n" << kToolTipCommonTitlePlaceholders
);
111 fWindowTitle
= new BTextControl("windowTitle", B_TRANSLATE("Window title:"),
113 fWindowTitle
->SetModificationMessage(
114 new BMessage(MSG_WINDOW_TITLE_SETTING_CHANGED
));
115 fWindowTitle
->SetToolTip(BString(B_TRANSLATE(
116 "The pattern specifying the window titles. The following placeholders\n"
117 "can be used:")) << "\n" << kTooTipSetWindowTitlePlaceholders
118 << "\n" << kToolTipCommonTitlePlaceholders
);
120 BLayoutBuilder::Group
<>(this)
121 .SetInsets(5, 5, 5, 5)
123 .Add(fTabTitle
->CreateLabelLayoutItem(), 0, 0)
124 .Add(fTabTitle
->CreateTextViewLayoutItem(), 1, 0)
125 .Add(fWindowTitle
->CreateLabelLayoutItem(), 0, 1)
126 .Add(fWindowTitle
->CreateTextViewLayoutItem(), 1, 1)
127 .Add(fWindowSizeField
->CreateLabelLayoutItem(), 0, 2)
128 .Add(fWindowSizeField
->CreateMenuBarLayoutItem(), 1, 2)
129 .Add(fFontField
->CreateLabelLayoutItem(), 0, 3)
130 .Add(fFontField
->CreateMenuBarLayoutItem(), 1, 3)
131 .Add(fEncodingField
->CreateLabelLayoutItem(), 0, 4)
132 .Add(fEncodingField
->CreateMenuBarLayoutItem(), 1, 4)
133 .Add(fColorSchemeField
->CreateLabelLayoutItem(), 0, 5)
134 .Add(fColorSchemeField
->CreateMenuBarLayoutItem(), 1, 5)
135 .Add(fColorField
->CreateLabelLayoutItem(), 0, 6)
136 .Add(fColorField
->CreateMenuBarLayoutItem(), 1, 6)
139 .Add(fColorControl
= new BColorControl(BPoint(10, 10),
140 B_CELLS_32x8
, 8.0, "", new BMessage(MSG_COLOR_CHANGED
)))
145 fTabTitle
->SetAlignment(B_ALIGN_RIGHT
, B_ALIGN_LEFT
);
146 fWindowTitle
->SetAlignment(B_ALIGN_RIGHT
, B_ALIGN_LEFT
);
147 fFontField
->SetAlignment(B_ALIGN_RIGHT
);
148 fWindowSizeField
->SetAlignment(B_ALIGN_RIGHT
);
149 fEncodingField
->SetAlignment(B_ALIGN_RIGHT
);
150 fColorField
->SetAlignment(B_ALIGN_RIGHT
);
151 fColorSchemeField
->SetAlignment(B_ALIGN_RIGHT
);
155 BTextControl
* redInput
= (BTextControl
*)fColorControl
->ChildAt(0);
156 BTextControl
* greenInput
= (BTextControl
*)fColorControl
->ChildAt(1);
157 BTextControl
* blueInput
= (BTextControl
*)fColorControl
->ChildAt(2);
159 redInput
->SetAlignment(B_ALIGN_RIGHT
, B_ALIGN_LEFT
);
160 greenInput
->SetAlignment(B_ALIGN_RIGHT
, B_ALIGN_LEFT
);
161 blueInput
->SetAlignment(B_ALIGN_RIGHT
, B_ALIGN_LEFT
);
166 AppearancePrefView::Revert()
168 PrefHandler
* pref
= PrefHandler::Default();
170 fTabTitle
->SetText(pref
->getString(PREF_TAB_TITLE
));
171 fWindowTitle
->SetText(pref
->getString(PREF_WINDOW_TITLE
));
173 fBlinkCursor
->SetValue(pref
->getBool(PREF_BLINK_CURSOR
));
174 fAllowBold
->SetValue(pref
->getBool(PREF_ALLOW_BOLD
));
175 fWarnOnExit
->SetValue(pref
->getBool(PREF_WARN_ON_EXIT
));
177 _SetCurrentColorScheme();
178 _SetEncoding(pref
->getString(PREF_TEXT_ENCODING
));
179 _SetWindowSize(pref
->getInt32(PREF_ROWS
), pref
->getInt32(PREF_COLS
));
180 fColorControl
->SetValue(pref
->getRGB(PREF_TEXT_FORE_COLOR
));
182 const char* family
= pref
->getString(PREF_HALF_FONT_FAMILY
);
183 const char* style
= pref
->getString(PREF_HALF_FONT_STYLE
);
184 const char* size
= pref
->getString(PREF_HALF_FONT_SIZE
);
186 _MarkSelectedFont(family
, style
, size
);
191 AppearancePrefView::AttachedToWindow()
193 fTabTitle
->SetTarget(this);
194 fWindowTitle
->SetTarget(this);
195 fBlinkCursor
->SetTarget(this);
196 fAllowBold
->SetTarget(this);
197 fWarnOnExit
->SetTarget(this);
199 fFontField
->Menu()->SetTargetForItems(this);
200 for (int32 i
= 0; i
< fFontField
->Menu()->CountItems(); i
++) {
201 BMenu
* fontSizeMenu
= fFontField
->Menu()->SubmenuAt(i
);
202 if (fontSizeMenu
== NULL
)
205 fontSizeMenu
->SetTargetForItems(this);
208 fColorControl
->SetTarget(this);
209 fColorField
->Menu()->SetTargetForItems(this);
210 fColorSchemeField
->Menu()->SetTargetForItems(this);
211 fWindowSizeField
->Menu()->SetTargetForItems(this);
212 fEncodingField
->Menu()->SetTargetForItems(this);
214 _SetCurrentColorScheme();
220 AppearancePrefView::MessageReceived(BMessage
* msg
)
222 bool modified
= false;
225 case MSG_HALF_FONT_CHANGED
:
227 const char* family
= NULL
;
228 const char* style
= NULL
;
229 const char* size
= NULL
;
230 if (msg
->FindString("font_family", &family
) != B_OK
231 || msg
->FindString("font_style", &style
) != B_OK
232 || msg
->FindString("font_size", &size
) != B_OK
) {
236 PrefHandler
* pref
= PrefHandler::Default();
237 const char* currentFamily
238 = pref
->getString(PREF_HALF_FONT_FAMILY
);
239 const char* currentStyle
240 = pref
->getString(PREF_HALF_FONT_STYLE
);
241 const char* currentSize
242 = pref
->getString(PREF_HALF_FONT_SIZE
);
244 if (currentFamily
== NULL
|| strcmp(currentFamily
, family
) != 0
245 || currentStyle
== NULL
|| strcmp(currentStyle
, style
) != 0
246 || currentSize
== NULL
|| strcmp(currentSize
, size
) != 0) {
247 pref
->setString(PREF_HALF_FONT_FAMILY
, family
);
248 pref
->setString(PREF_HALF_FONT_STYLE
, style
);
249 pref
->setString(PREF_HALF_FONT_SIZE
, size
);
250 _MarkSelectedFont(family
, style
, size
);
256 case MSG_COLOR_CHANGED
:
258 const BMessage
* itemMessage
259 = fColorField
->Menu()->FindMarked()->Message();
260 const char* label
= NULL
;
261 if (itemMessage
->FindString("label", &label
) != B_OK
)
263 rgb_color oldColor
= PrefHandler::Default()->getRGB(label
);
264 if (oldColor
!= fColorControl
->ValueAsColor()) {
265 BMenuItem
* item
= fColorSchemeField
->Menu()->FindMarked();
266 if (strcmp(item
->Label(), gCustomColorScheme
.name
) != 0) {
267 item
->SetMarked(false);
268 item
= fColorSchemeField
->Menu()->FindItem(
269 gCustomColorScheme
.name
);
271 item
->SetMarked(true);
274 PrefHandler::Default()->setRGB(label
,
275 fColorControl
->ValueAsColor());
281 case MSG_COLOR_SCHEME_CHANGED
:
283 color_scheme
* newScheme
= NULL
;
284 if (msg
->FindPointer("color_scheme",
285 (void**)&newScheme
) == B_OK
) {
286 _ChangeColorScheme(newScheme
);
287 const char* label
= NULL
;
288 if (fColorField
->Menu()->FindMarked()->Message()->FindString(
289 "label", &label
) == B_OK
)
290 fColorControl
->SetValue(
291 PrefHandler::Default()->getRGB(label
));
297 case MSG_COLOR_FIELD_CHANGED
:
299 const char* label
= NULL
;
300 if (msg
->FindString("label", &label
) == B_OK
)
301 fColorControl
->SetValue(PrefHandler::Default()->getRGB(label
));
305 case MSG_COLS_CHANGED
:
307 int rows
= msg
->FindInt32("rows");
308 int columns
= msg
->FindInt32("columns");
309 _SetWindowSize(rows
, columns
);
310 PrefHandler
* handler
= PrefHandler::Default();
311 if (handler
->getInt32(PREF_ROWS
) != rows
) {
312 PrefHandler::Default()->setInt32(PREF_ROWS
, rows
);
315 if (handler
->getInt32(PREF_COLS
) != columns
) {
316 PrefHandler::Default()->setInt32(PREF_COLS
, columns
);
323 case MSG_BLINK_CURSOR_CHANGED
:
324 if (PrefHandler::Default()->getBool(PREF_BLINK_CURSOR
)
325 != fBlinkCursor
->Value()) {
326 PrefHandler::Default()->setBool(PREF_BLINK_CURSOR
,
327 fBlinkCursor
->Value());
332 case MSG_ALLOW_BOLD_CHANGED
:
333 if (PrefHandler::Default()->getBool(PREF_ALLOW_BOLD
)
334 != fAllowBold
->Value()) {
335 PrefHandler::Default()->setBool(PREF_ALLOW_BOLD
,
336 fAllowBold
->Value());
341 case MSG_WARN_ON_EXIT_CHANGED
:
342 if (PrefHandler::Default()->getBool(PREF_WARN_ON_EXIT
)
343 != fWarnOnExit
->Value()) {
344 PrefHandler::Default()->setBool(PREF_WARN_ON_EXIT
,
345 fWarnOnExit
->Value());
350 case MSG_TAB_TITLE_SETTING_CHANGED
:
352 BString
oldValue(PrefHandler::Default()->getString(PREF_TAB_TITLE
));
353 if (oldValue
!= fTabTitle
->Text()) {
354 PrefHandler::Default()->setString(PREF_TAB_TITLE
,
361 case MSG_WINDOW_TITLE_SETTING_CHANGED
:
363 BString
oldValue(PrefHandler::Default()->getString(
365 if (oldValue
!= fWindowTitle
->Text()) {
366 PrefHandler::Default()->setString(PREF_WINDOW_TITLE
,
367 fWindowTitle
->Text());
374 BView::MessageReceived(msg
);
379 fTerminalMessenger
.SendMessage(msg
);
381 BMessenger
messenger(this);
382 messenger
.SendMessage(MSG_PREF_MODIFIED
);
388 AppearancePrefView::_ChangeColorScheme(color_scheme
* scheme
)
390 PrefHandler
* pref
= PrefHandler::Default();
392 pref
->setRGB(PREF_TEXT_FORE_COLOR
, scheme
->text_fore_color
);
393 pref
->setRGB(PREF_TEXT_BACK_COLOR
, scheme
->text_back_color
);
394 pref
->setRGB(PREF_SELECT_FORE_COLOR
, scheme
->select_fore_color
);
395 pref
->setRGB(PREF_SELECT_BACK_COLOR
, scheme
->select_back_color
);
396 pref
->setRGB(PREF_CURSOR_FORE_COLOR
, scheme
->cursor_fore_color
);
397 pref
->setRGB(PREF_CURSOR_BACK_COLOR
, scheme
->cursor_back_color
);
402 AppearancePrefView::_SetCurrentColorScheme()
404 PrefHandler
* pref
= PrefHandler::Default();
406 gCustomColorScheme
.text_fore_color
= pref
->getRGB(PREF_TEXT_FORE_COLOR
);
407 gCustomColorScheme
.text_back_color
= pref
->getRGB(PREF_TEXT_BACK_COLOR
);
408 gCustomColorScheme
.select_fore_color
= pref
->getRGB(PREF_SELECT_FORE_COLOR
);
409 gCustomColorScheme
.select_back_color
= pref
->getRGB(PREF_SELECT_BACK_COLOR
);
410 gCustomColorScheme
.cursor_fore_color
= pref
->getRGB(PREF_CURSOR_FORE_COLOR
);
411 gCustomColorScheme
.cursor_back_color
= pref
->getRGB(PREF_CURSOR_BACK_COLOR
);
413 const char* currentSchemeName
= NULL
;
415 for (const color_scheme
** schemes
= gPredefinedColorSchemes
;
416 *schemes
!= NULL
; schemes
++) {
417 if (gCustomColorScheme
== **schemes
) {
418 currentSchemeName
= (*schemes
)->name
;
423 // If the scheme is not one of the known ones, assume a custom one.
424 if (currentSchemeName
== NULL
)
425 currentSchemeName
= "Custom";
427 for (int32 i
= 0; i
< fColorSchemeField
->Menu()->CountItems(); i
++) {
428 BMenuItem
* item
= fColorSchemeField
->Menu()->ItemAt(i
);
429 if (strcmp(item
->Label(), currentSchemeName
) == 0) {
430 item
->SetMarked(true);
438 AppearancePrefView::_SetEncoding(const char* name
)
440 const BPrivate::BCharacterSet
* charset
441 = BPrivate::BCharacterSetRoster::FindCharacterSetByName(name
);
444 int code
= charset
->GetConversionID();
445 for (int32 i
= 0; i
< fEncodingField
->Menu()->CountItems(); i
++) {
446 BMenuItem
* item
= fEncodingField
->Menu()->ItemAt(i
);
447 BMessage
* msg
= item
->Message();
448 if (msg
->FindInt32("op") == code
) {
449 item
->SetMarked(true);
457 AppearancePrefView::_SetWindowSize(int rows
, int cols
)
459 for (int32 i
= 0; i
< fWindowSizeField
->Menu()->CountItems(); i
++) {
460 BMenuItem
* item
= fWindowSizeField
->Menu()->ItemAt(i
);
461 BMessage
* msg
= item
->Message();
462 if (msg
->FindInt32("rows") == rows
&& msg
->FindInt32("columns") == cols
) {
463 item
->SetMarked(true);
471 AppearancePrefView::_MakeFontMenu(uint32 command
,
472 const char* defaultFamily
, const char* defaultStyle
)
474 BPopUpMenu
* menu
= new BPopUpMenu("");
475 int32 numFamilies
= count_font_families();
476 for (int32 i
= 0; i
< numFamilies
; i
++) {
479 if (get_font_family(i
, &family
, &flags
) == B_OK
) {
482 int32 numStyles
= count_font_styles(family
);
483 for (int32 j
= 0; j
< numStyles
; j
++) {
484 if (get_font_style(family
, j
, &style
) == B_OK
) {
485 font
.SetFamilyAndStyle(family
, style
);
486 if (IsFontUsable(font
)) {
487 BMessage
* message
= new BMessage(command
);
489 = PrefHandler::Default()->getString(PREF_HALF_FONT_SIZE
);
490 message
->AddString("font_family", family
);
491 message
->AddString("font_style", style
);
492 message
->AddString("font_size", size
);
493 char fontMenuLabel
[134];
494 snprintf(fontMenuLabel
, sizeof(fontMenuLabel
),
495 "%s - %s", family
, style
);
496 BMenu
* fontSizeMenu
= _MakeFontSizeMenu(fontMenuLabel
,
497 MSG_HALF_FONT_CHANGED
, family
, style
, size
);
498 BMenuItem
* item
= new BMenuItem(fontSizeMenu
, message
);
500 if (strcmp(defaultFamily
, family
) == 0
501 && strcmp(defaultStyle
, style
) == 0)
502 item
->SetMarked(true);
509 if (menu
->FindMarked() == NULL
)
510 menu
->ItemAt(0)->SetMarked(true);
517 AppearancePrefView::_MakeFontSizeMenu(const char* label
, uint32 command
,
518 const char* family
, const char* style
, const char* size
)
520 BMenu
* menu
= new BMenu(label
);
521 menu
->SetRadioMode(true);
522 menu
->SetLabelFromMarked(false);
525 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 28, 32, 36, 0
530 for (uint32 i
= 0; sizes
[i
]; i
++) {
532 fontSize
<< sizes
[i
];
533 BMessage
* message
= new BMessage(command
);
534 message
->AddString("font_family", family
);
535 message
->AddString("font_style", style
);
536 message
->AddString("font_size", fontSize
.String());
537 BMenuItem
* item
= new BMenuItem(fontSize
.String(), message
);
539 if (sizes
[i
] == atoi(size
)) {
540 item
->SetMarked(true);
546 for (uint32 i
= 0; sizes
[i
]; i
++) {
547 if (sizes
[i
] > atoi(size
)) {
548 BMessage
* message
= new BMessage(command
);
549 message
->AddString("font_family", family
);
550 message
->AddString("font_style", style
);
551 message
->AddString("font_size", size
);
552 BMenuItem
* item
= new BMenuItem(size
, message
);
553 item
->SetMarked(true);
554 menu
->AddItem(item
, i
);
564 /*static*/ BPopUpMenu
*
565 AppearancePrefView::_MakeMenu(uint32 msg
, const char** items
,
566 const char* defaultItemName
)
568 BPopUpMenu
* menu
= new BPopUpMenu("");
571 if (strcmp((*items
), "") == 0)
572 menu
->AddSeparatorItem();
574 BMessage
* message
= new BMessage(msg
);
575 message
->AddString("label", *items
);
576 BMenuItem
* item
= new BMenuItem(B_TRANSLATE(*items
), message
);
578 if (strcmp(*items
, defaultItemName
) == 0)
579 item
->SetMarked(true);
589 /*static*/ BPopUpMenu
*
590 AppearancePrefView::_MakeColorSchemeMenu(uint32 msg
, const color_scheme
** items
,
591 const color_scheme
* defaultItemName
)
593 BPopUpMenu
* menu
= new BPopUpMenu("");
597 if (strcmp((*items
)->name
, "") == 0)
598 menu
->AddSeparatorItem();
600 BMessage
* message
= new BMessage(msg
);
601 message
->AddPointer("color_scheme", (const void*)*items
);
602 menu
->AddItem(new BMenuItem((*items
)->name
, message
));
613 AppearancePrefView::_MarkSelectedFont(const char* family
, const char* style
,
616 char fontMenuLabel
[134];
617 snprintf(fontMenuLabel
, sizeof(fontMenuLabel
), "%s - %s", family
, style
);
619 // mark the selected font
620 BMenuItem
* selectedFont
= fFontField
->Menu()->FindItem(fontMenuLabel
);
621 if (selectedFont
!= NULL
)
622 selectedFont
->SetMarked(true);
624 // mark the selected font size on all font menus
625 for (int32 i
= 0; i
< fFontField
->Menu()->CountItems(); i
++) {
626 BMenu
* fontSizeMenu
= fFontField
->Menu()->SubmenuAt(i
);
627 if (fontSizeMenu
== NULL
)
630 BMenuItem
* item
= fontSizeMenu
->FindItem(size
);
632 item
->SetMarked(true);