Implemented support for dynamic tab and window titles:

* Added settings for tab and window titles. Both are strings with optional
  placeholders for tab/terminal index, currently active process name and
  current directory.
* Added a generic utility class PatternEvaluator that allows to expand this
  kind of pattern strings and callback classes
  [Tab,Window]TitlePlaceholderMapper that provide the specific expansion for
  the tab and window title placeholders.
* TermWindow:
  - Separated the notions of session (== tab) and window titles. The tty
    clients no longer set the window, but the session title.
  - Use the patterns instead of the hard-coded window/tab titles.
  - Recompute all titles once a second, so changes of running programs are
    reflected.
* The default patterns for tab and window titles are "%1d: %p" (last CWD
  component and name of the running process) and "Terminal %i: %t" (Terminal
  ID and active tab title). Unfortunately the space on the tabs is seriously
  limited, so that the tab title is virtually always truncated. Ideas welcome.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39473 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-11-17 23:46:13 +00:00
parent e492be3195
commit 02ee32bb0d
13 changed files with 513 additions and 50 deletions

View File

@ -106,17 +106,48 @@ AppearancePrefView::AppearancePrefView(const char* name,
colorsPopUp);
fColorField->SetEnabled(false);
fTabTitle = new BTextControl("tabTitle", B_TRANSLATE("Tab title:"), "",
NULL);
fTabTitle->SetModificationMessage(
new BMessage(MSG_TAB_TITLE_SETTING_CHANGED));
fTabTitle->SetToolTip(B_TRANSLATE(
"The pattern specifying the tab titles. The following placeholders\n"
"can be used:\n"
"\t%d\t-\tThe current working directory of the active process.\n"
"\t\t\tOptionally the maximum number of path components can be\n"
"\t\t\tspecified. E.g. '%2d' for at most two components.\n"
"\t%i\t-\tThe index of the tab.\n"
"\t%p\t-\tThe name of the active process.\n"
"\t%%\t-\tThe character '%'."));
fWindowTitle = new BTextControl("windowTitle", B_TRANSLATE("Window title:"),
"", NULL);
fWindowTitle->SetModificationMessage(
new BMessage(MSG_WINDOW_TITLE_SETTING_CHANGED));
fWindowTitle->SetToolTip(B_TRANSLATE(
"The pattern specifying the window titles. The following placeholders\n"
"can be used:\n"
"\t%d\t-\tThe current working directory of the active process in the.\n"
"\t\t\tcurrent tab. Optionally the maximum number of path components\n"
"\t\t\tcan be specified. E.g. '%2d' for at most two components.\n"
"\t%i\t-\tThe index of the window.\n"
"\t%p\t-\tThe name of the active process in the current tab.\n"
"\t%t\t-\tThe title of the current tab.\n"
"\t%%\t-\tThe character '%'."));
BLayoutBuilder::Group<>(this)
.SetInsets(5, 5, 5, 5)
.AddGrid(5, 5)
.Add(fFont->CreateLabelLayoutItem(), 0, 0)
.Add(fFont->CreateMenuBarLayoutItem(), 1, 0)
.Add(fFontSize->CreateLabelLayoutItem(), 0, 1)
.Add(fFontSize->CreateMenuBarLayoutItem(), 1, 1)
.Add(fColorSchemaField->CreateLabelLayoutItem(), 0, 2)
.Add(fColorSchemaField->CreateMenuBarLayoutItem(), 1, 2)
.Add(fColorField->CreateLabelLayoutItem(), 0, 3)
.Add(fColorField->CreateMenuBarLayoutItem(), 1, 3)
.AddTextControl(fTabTitle, 0, 0, B_ALIGN_RIGHT)
.AddTextControl(fWindowTitle, 0, 1, B_ALIGN_RIGHT)
.Add(fFont->CreateLabelLayoutItem(), 0, 2)
.Add(fFont->CreateMenuBarLayoutItem(), 1, 2)
.Add(fFontSize->CreateLabelLayoutItem(), 0, 3)
.Add(fFontSize->CreateMenuBarLayoutItem(), 1, 3)
.Add(fColorSchemaField->CreateLabelLayoutItem(), 0, 4)
.Add(fColorSchemaField->CreateMenuBarLayoutItem(), 1, 4)
.Add(fColorField->CreateLabelLayoutItem(), 0, 5)
.Add(fColorField->CreateMenuBarLayoutItem(), 1, 5)
.End()
.AddGlue()
.Add(fColorControl = new BColorControl(BPoint(10, 10),
@ -128,6 +159,9 @@ AppearancePrefView::AppearancePrefView(const char* name,
fColorField->SetAlignment(B_ALIGN_RIGHT);
fColorSchemaField->SetAlignment(B_ALIGN_RIGHT);
fTabTitle->SetText(PrefHandler::Default()->getString(PREF_TAB_TITLE));
fWindowTitle->SetText(PrefHandler::Default()->getString(PREF_WINDOW_TITLE));
fColorControl->SetEnabled(false);
fColorControl->SetValue(
PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR));
@ -158,6 +192,9 @@ AppearancePrefView::GetPreferredSize(float* _width, float* _height)
void
AppearancePrefView::Revert()
{
fTabTitle->SetText(PrefHandler::Default()->getString(PREF_TAB_TITLE));
fWindowTitle->SetText(PrefHandler::Default()->getString(PREF_WINDOW_TITLE));
fWarnOnExit->SetValue(PrefHandler::Default()->getBool(
PREF_WARN_ON_EXIT));
@ -175,6 +212,8 @@ AppearancePrefView::Revert()
void
AppearancePrefView::AttachedToWindow()
{
fTabTitle->SetTarget(this);
fWindowTitle->SetTarget(this);
fWarnOnExit->SetTarget(this);
fFontSize->Menu()->SetTargetForItems(this);
@ -271,6 +310,30 @@ AppearancePrefView::MessageReceived(BMessage* msg)
modified = true;
}
break;
case MSG_TAB_TITLE_SETTING_CHANGED:
{
BString oldValue(PrefHandler::Default()->getString(PREF_TAB_TITLE));
if (oldValue != fTabTitle->Text()) {
PrefHandler::Default()->setString(PREF_TAB_TITLE,
fTabTitle->Text());
modified = true;
}
break;
}
case MSG_WINDOW_TITLE_SETTING_CHANGED:
{
BString oldValue(PrefHandler::Default()->getString(
PREF_WINDOW_TITLE));
if (oldValue != fWindowTitle->Text()) {
PrefHandler::Default()->setString(PREF_WINDOW_TITLE,
fWindowTitle->Text());
modified = true;
}
break;
}
default:
BView::MessageReceived(msg);
return;

View File

@ -13,28 +13,31 @@
#include <String.h>
const ulong MSG_HALF_FONT_CHANGED = 'mchf';
const ulong MSG_HALF_SIZE_CHANGED = 'mchs';
const ulong MSG_FULL_FONT_CHANGED = 'mcff';
const ulong MSG_FULL_SIZE_CHANGED = 'mcfs';
const ulong MSG_COLOR_FIELD_CHANGED = 'mccf';
const ulong MSG_COLOR_CHANGED = 'mcbc';
const ulong MSG_COLOR_SCHEMA_CHANGED = 'mccs';
static const uint32 MSG_HALF_FONT_CHANGED = 'mchf';
static const uint32 MSG_HALF_SIZE_CHANGED = 'mchs';
static const uint32 MSG_FULL_FONT_CHANGED = 'mcff';
static const uint32 MSG_FULL_SIZE_CHANGED = 'mcfs';
static const uint32 MSG_COLOR_FIELD_CHANGED = 'mccf';
static const uint32 MSG_COLOR_CHANGED = 'mcbc';
static const uint32 MSG_COLOR_SCHEMA_CHANGED = 'mccs';
const ulong MSG_WARN_ON_EXIT_CHANGED = 'mwec';
const ulong MSG_COLS_CHANGED = 'mccl';
const ulong MSG_ROWS_CHANGED = 'mcrw';
const ulong MSG_HISTORY_CHANGED = 'mhst';
static const uint32 MSG_TAB_TITLE_SETTING_CHANGED = 'mtts';
static const uint32 MSG_WINDOW_TITLE_SETTING_CHANGED = 'mwts';
static const uint32 MSG_WARN_ON_EXIT_CHANGED = 'mwec';
static const uint32 MSG_COLS_CHANGED = 'mccl';
static const uint32 MSG_ROWS_CHANGED = 'mcrw';
static const uint32 MSG_HISTORY_CHANGED = 'mhst';
const ulong MSG_PREF_MODIFIED = 'mpmo';
static const uint32 MSG_PREF_MODIFIED = 'mpmo';
struct color_schema;
class BCheckBox;
class BColorControl;
class BMenu;
class BMenuField;
class BPopUpMenu;
class BCheckBox;
class BTextControl;
class AppearancePrefView : public BGroupView {
@ -76,6 +79,9 @@ private:
BMenuField* fColorField;
BColorControl* fColorControl;
BTextControl* fTabTitle;
BTextControl* fWindowTitle;
BMessenger fTerminalMessenger;
};

View File

@ -17,6 +17,7 @@ Application Terminal :
Globals.cpp
HistoryBuffer.cpp
InlineInput.cpp
PatternEvaluator.cpp
PrefHandler.cpp
PrefWindow.cpp
Shell.cpp
@ -29,6 +30,7 @@ Application Terminal :
TermScrollView.cpp
TermView.cpp
TermWindow.cpp
TitlePlaceholderMapper.cpp
VTKeyTbl.c
VTPrsTbl.c
: be $(HAIKU_LOCALE_LIBS) tracker textencoding $(TARGET_LIBSUPC++)

View File

@ -0,0 +1,75 @@
/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PatternEvaluator.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
// #pragma mark - PatternEvaluator
/*static*/ BString
PatternEvaluator::Evaluate(const char* pattern, PlaceholderMapper& mapper)
{
BString result;
while (*pattern != '\0') {
// find next placeholder
const char* placeholder = strchr(pattern, '%');
if (placeholder == NULL)
return result.Append(pattern);
// append skipped chars
if (placeholder != pattern)
result.Append(pattern, placeholder - pattern);
pattern = placeholder + 1;
// check for an escaped '%'
if (*pattern == '%') {
result += '%';
pattern++;
continue;
}
// parse a number, if there is one
int64 number = 0;
bool hasNumber = false;
if (isdigit(*pattern)) {
char* numberEnd;
number = strtoll(pattern, &numberEnd, 10);
pattern = numberEnd;
hasNumber = true;
}
BString mappedValue;
if (*pattern != '\0' && mapper.MapPlaceholder(*pattern,
number, hasNumber, mappedValue)) {
// mapped successfully -- append the replacement string
result += mappedValue;
pattern++;
} else {
// something went wrong -- just append the literal part of the
// pattern
result.Append(placeholder, pattern - placeholder);
}
}
return result;
}
// #pragma mark - PlaceholderMapper
PatternEvaluator::PlaceholderMapper::~PlaceholderMapper()
{
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PATTERN_EVALUATOR_H
#define PATTERN_EVALUATOR_H
#include <String.h>
class PatternEvaluator {
public:
class PlaceholderMapper;
public:
static BString Evaluate(const char* pattern,
PlaceholderMapper& mapper);
};
class PatternEvaluator::PlaceholderMapper {
public:
virtual ~PlaceholderMapper();
virtual bool MapPlaceholder(char placeholder,
int64 number, bool numberGiven,
BString& _string) = 0;
};
#endif // PATTERN_EVALUATOR_H

View File

@ -57,6 +57,8 @@ static const pref_defaults kTermDefaults[] = {
{ PREF_GUI_LANGUAGE, "English"},
{ PREF_IM_AWARE, "0"},
{ PREF_TAB_TITLE, "%1d: %p" },
{ PREF_WINDOW_TITLE, "Terminal %i: %t" },
{ PREF_WARN_ON_EXIT, PREF_TRUE },
{ NULL, NULL},

View File

@ -59,6 +59,7 @@ main()
TermApp::TermApp()
: BApplication(TERM_SIGNATURE),
fStartFullscreen(false),
fWindowTitleUserDefined(false),
fWindowNumber(-1),
fTermWindow(NULL),
fArgs(NULL)
@ -222,8 +223,10 @@ TermApp::ArgvReceived(int32 argc, char **argv)
return;
}
if (fArgs->Title() != NULL)
if (fArgs->Title() != NULL) {
fWindowTitle = fArgs->Title();
fWindowTitleUserDefined = true;
}
fStartFullscreen = fArgs->FullScreen();
}
@ -361,8 +364,8 @@ status_t
TermApp::_MakeTermWindow(BRect &frame, uint32 workspaces)
{
try {
fTermWindow = new TermWindow(frame, fWindowTitle.String(), workspaces,
fArgs);
fTermWindow = new TermWindow(frame, fWindowTitle,
fWindowTitleUserDefined, fWindowNumber, workspaces, fArgs);
} catch (int error) {
return (status_t)error;
} catch (...) {

View File

@ -85,6 +85,7 @@ private:
private:
bool fStartFullscreen;
BString fWindowTitle;
bool fWindowTitleUserDefined;
int32 fWindowNumber;
BWindow* fTermWindow;

View File

@ -131,6 +131,9 @@ static const char* const PREF_GUI_LANGUAGE = "Language";
static const char* const PREF_WARN_ON_EXIT = "Warn on exit";
static const char* const PREF_TAB_TITLE = "Tab title";
static const char* const PREF_WINDOW_TITLE = "Window title";
// Color type
enum {
TEXT_FOREGROUND_COLOR,

View File

@ -44,6 +44,7 @@
#include "TermConst.h"
#include "TermScrollView.h"
#include "TermView.h"
#include "TitlePlaceholderMapper.h"
const static int32 kMaxTabs = 6;
@ -55,6 +56,7 @@ const static uint32 kCloseView = 'ClVw';
const static uint32 kIncreaseFontSize = 'InFs';
const static uint32 kDecreaseFontSize = 'DcFs';
const static uint32 kSetActiveTab = 'STab';
const static uint32 kUpdateTitles = 'UPti';
#undef B_TRANSLATE_CONTEXT
@ -100,8 +102,7 @@ private:
struct TermWindow::Session {
int32 id;
BString name;
BString windowTitle;
Title title;
TermViewContainerView* containerView;
Session(int32 id, TermViewContainerView* containerView)
@ -109,8 +110,9 @@ struct TermWindow::Session {
id(id),
containerView(containerView)
{
name = B_TRANSLATE("Shell ");
name << id;
title.title = B_TRANSLATE("Shell ");
title.title << id;
title.patternUserDefined = false;
}
};
@ -140,12 +142,14 @@ private:
};
TermWindow::TermWindow(BRect frame, const char* title, uint32 workspaces,
TermWindow::TermWindow(BRect frame, const BString& title,
bool isUserDefinedTitle, int32 windowIndex, uint32 workspaces,
Arguments* args)
:
BWindow(frame, title, B_DOCUMENT_WINDOW,
B_CURRENT_WORKSPACE | B_QUIT_ON_WINDOW_CLOSE, workspaces),
fInitialTitle(title),
fWindowIndex(windowIndex),
fTitleUpdateRunner(this, BMessage(kUpdateTitles), 1000000),
fTabView(NULL),
fMenubar(NULL),
fFilemenu(NULL),
@ -166,6 +170,12 @@ TermWindow::TermWindow(BRect frame, const char* title, uint32 workspaces,
fMatchWord(false),
fFullScreen(false)
{
// apply the title settings
fTitle.title = title;
fTitle.pattern = title;
fTitle.patternUserDefined = isUserDefinedTitle;
_TitleSettingsChanged();
_InitWindow();
_AddTab(args);
}
@ -189,15 +199,13 @@ TermWindow::~TermWindow()
void
TermWindow::SetSessionWindowTitle(TermView* termView, const char* title)
TermWindow::SetSessionTitle(TermView* termView, const char* title)
{
int32 index = _IndexOfTermView(termView);
if (Session* session = (Session*)fSessions.ItemAt(index)) {
session->windowTitle = title;
BTab* tab = fTabView->TabAt(index);
tab->SetLabel(session->windowTitle.String());
if (index == fTabView->Selection())
SetTitle(session->windowTitle.String());
session->title.pattern = title;
session->title.patternUserDefined = true;
_UpdateSessionTitle(index);
}
}
@ -205,9 +213,7 @@ TermWindow::SetSessionWindowTitle(TermView* termView, const char* title)
void
TermWindow::SessionChanged()
{
int32 index = fTabView->Selection();
if (Session* session = (Session*)fSessions.ItemAt(index))
SetTitle(session->windowTitle.String());
_UpdateSessionTitle(fTabView->Selection());
}
@ -509,6 +515,11 @@ TermWindow::MessageReceived(BMessage *message)
fPrefWindow = NULL;
break;
case MSG_WINDOW_TITLE_SETTING_CHANGED:
case MSG_TAB_TITLE_SETTING_CHANGED:
_TitleSettingsChanged();
break;
case MENU_FIND_STRING:
if (!fFindPanel) {
fFindPanel = new FindWindow(this, fFindString, fFindSelection,
@ -755,6 +766,10 @@ TermWindow::MessageReceived(BMessage *message)
break;
}
case kUpdateTitles:
_UpdateTitles();
break;
default:
BWindow::MessageReceived(message);
break;
@ -870,7 +885,6 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
fTabView->SetScrollView(scrollView);
Session* session = new Session(_NewSessionID(), containerView);
session->windowTitle = fInitialTitle;
fSessions.AddItem(session);
BFont font;
@ -905,10 +919,6 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
BTab* tab = new BTab;
fTabView->AddTab(scrollView, tab);
tab->SetLabel(session->name.String());
// TODO: Use a better name. For example, do like MacOS X's Terminal
// and update the title using the last executed command ?
// Or like Gnome's Terminal and use the current path ?
view->SetScrollBar(scrollView->ScrollBar(B_VERTICAL));
view->SetMouseClipboard(gMouseClipboard);
view->SetEncoding(EncodingID(
@ -916,8 +926,10 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
_SetTermColors(containerView);
// TODO: No fTabView->Select(tab); ?
fTabView->Select(fTabView->CountTabs() - 1);
int32 tabIndex = fTabView->CountTabs() - 1;
fTabView->Select(tabIndex);
_UpdateSessionTitle(tabIndex);
} catch (...) {
// most probably out of memory. That's bad.
// TODO: Should cleanup, I guess
@ -1096,6 +1108,72 @@ TermWindow::_MakeWindowSizeMenu()
}
void
TermWindow::_TitleSettingsChanged()
{
if (!fTitle.patternUserDefined)
fTitle.pattern = PrefHandler::Default()->getString(PREF_WINDOW_TITLE);
fSessionTitlePattern = PrefHandler::Default()->getString(PREF_TAB_TITLE);
_UpdateTitles();
}
void
TermWindow::_UpdateTitles()
{
int32 sessionCount = fSessions.CountItems();
for (int32 i = 0; i < sessionCount; i++)
_UpdateSessionTitle(i);
}
void
TermWindow::_UpdateSessionTitle(int32 index)
{
Session* session = (Session*)fSessions.ItemAt(index);
if (session == NULL)
return;
// get the active process info
ActiveProcessInfo activeProcessInfo;
if (!_TermViewAt(index)->GetActiveProcessInfo(activeProcessInfo))
return;
// evaluate the session title pattern
BString sessionTitlePattern = session->title.patternUserDefined
? session->title.pattern : fSessionTitlePattern;
TabTitlePlaceholderMapper tabMapper(activeProcessInfo, session->id);
const BString& sessionTitle = PatternEvaluator::Evaluate(
sessionTitlePattern, tabMapper);
// set the tab title
if (sessionTitle != session->title.title) {
session->title.title = sessionTitle;
BTab* tab = fTabView->TabAt(index);
tab->SetLabel(session->title.title);
fTabView->Invalidate(fTabView->TabFrame(index));
}
// If this is the active tab, also recompute the window title.
if (index != fTabView->Selection())
return;
// evaluate the window title pattern
WindowTitlePlaceholderMapper windowMapper(activeProcessInfo, fWindowIndex,
sessionTitle);
const BString& windowTitle = PatternEvaluator::Evaluate(fTitle.pattern,
windowMapper);
// set the window title
if (windowTitle != fTitle.title) {
fTitle.title = windowTitle;
SetTitle(fTitle.title);
}
}
int32
TermWindow::_NewSessionID()
{
@ -1152,6 +1230,6 @@ CustomTermView::NotifyQuit(int32 reason)
void
CustomTermView::SetTitle(const char* title)
{
dynamic_cast<TermWindow*>(Window())->SetSessionWindowTitle(this, title);
dynamic_cast<TermWindow*>(Window())->SetSessionTitle(this, title);
}

View File

@ -32,6 +32,7 @@
#define TERM_WINDOW_H
#include <MessageRunner.h>
#include <String.h>
#include <Window.h>
@ -49,11 +50,12 @@ class TermViewContainerView;
class TermWindow : public BWindow {
public:
TermWindow(BRect frame, const char* title,
TermWindow(BRect frame, const BString& title,
bool isUserDefinedTitle, int32 windowIndex,
uint32 workspaces, Arguments* args);
virtual ~TermWindow();
void SetSessionWindowTitle(TermView* termView,
void SetSessionTitle(TermView* termView,
const char* title);
void SessionChanged();
@ -66,6 +68,12 @@ protected:
virtual void FrameResized(float newWidth, float newHeight);
private:
struct Title {
BString title;
BString pattern;
bool patternUserDefined;
};
struct Session;
class TabView;
friend class TabView;
@ -92,10 +100,18 @@ private:
void _CheckChildren();
void _ResizeView(TermView* view);
void _TitleSettingsChanged();
void _UpdateTitles();
void _UpdateSessionTitle(int32 index);
int32 _NewSessionID();
private:
BString fInitialTitle;
Title fTitle;
BString fSessionTitlePattern;
int32 fWindowIndex;
BMessageRunner fTitleUpdateRunner;
BList fSessions;
TabView* fTabView;

View File

@ -0,0 +1,121 @@
/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "TitlePlaceholderMapper.h"
// #pragma mark - TitlePlaceholderMapper
TitlePlaceholderMapper::TitlePlaceholderMapper(
const ActiveProcessInfo& processInfo)
:
fProcessInfo(processInfo)
{
}
#include <stdio.h>
bool
TitlePlaceholderMapper::MapPlaceholder(char placeholder, int64 number,
bool numberGiven, BString& _string)
{
switch (placeholder) {
case 'd':
{
// current working directory
// If a number is given, extract the respective number of rightmost
// components.
BString directory(fProcessInfo.CurrentDirectory());
if (numberGiven && number > 0) {
int32 index = directory.Length();
while (number > 0 && index > 0) {
index = directory.FindLast('/', index - 1);
number--;
}
if (index >= 0 && index + 1 < directory.Length())
directory.Remove(0, index + 1);
}
_string = directory;
return true;
}
case 'p':
// process name
_string = fProcessInfo.Name();
return true;
}
return false;
}
// #pragma mark - WindowTitlePlaceholderMapper
WindowTitlePlaceholderMapper::WindowTitlePlaceholderMapper(
const ActiveProcessInfo& processInfo, int32 windowIndex,
const BString& tabTitle)
:
TitlePlaceholderMapper(processInfo),
fWindowIndex(windowIndex),
fTabTitle(tabTitle)
{
}
bool
WindowTitlePlaceholderMapper::MapPlaceholder(char placeholder, int64 number,
bool numberGiven, BString& _string)
{
switch (placeholder) {
case 'i':
// window index
_string.Truncate(0);
_string << fWindowIndex;
return true;
case 't':
// the tab title
_string = fTabTitle;
return true;
}
return TitlePlaceholderMapper::MapPlaceholder(placeholder, number,
numberGiven, _string);
}
// #pragma mark - TabTitlePlaceholderMapper
TabTitlePlaceholderMapper::TabTitlePlaceholderMapper(
const ActiveProcessInfo& processInfo, int32 tabIndex)
:
TitlePlaceholderMapper(processInfo),
fTabIndex(tabIndex)
{
}
bool
TabTitlePlaceholderMapper::MapPlaceholder(char placeholder, int64 number,
bool numberGiven, BString& _string)
{
switch (placeholder) {
case 'i':
// tab index
_string.Truncate(0);
_string << fTabIndex;
return true;
}
return TitlePlaceholderMapper::MapPlaceholder(placeholder, number,
numberGiven, _string);
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef TITLE_PLACEHOLDER_MAPPER_H
#define TITLE_PLACEHOLDER_MAPPER_H
#include "ActiveProcessInfo.h"
#include "PatternEvaluator.h"
/*! Class mapping the placeholders common for window and tab titles.
*/
class TitlePlaceholderMapper : public PatternEvaluator::PlaceholderMapper {
public:
TitlePlaceholderMapper(
const ActiveProcessInfo& processInfo);
virtual bool MapPlaceholder(char placeholder,
int64 number, bool numberGiven,
BString& _string);
private:
ActiveProcessInfo fProcessInfo;
};
class WindowTitlePlaceholderMapper : public TitlePlaceholderMapper {
public:
WindowTitlePlaceholderMapper(
const ActiveProcessInfo& processInfo,
int32 windowIndex, const BString& tabTitle);
virtual bool MapPlaceholder(char placeholder,
int64 number, bool numberGiven,
BString& _string);
private:
int32 fWindowIndex;
BString fTabTitle;
};
class TabTitlePlaceholderMapper : public TitlePlaceholderMapper {
public:
TabTitlePlaceholderMapper(
const ActiveProcessInfo& processInfo,
int32 tabIndex);
virtual bool MapPlaceholder(char placeholder,
int64 number, bool numberGiven,
BString& _string);
private:
int32 fTabIndex;
};
#endif // TITLE_PLACEHOLDER_MAPPER_H