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:
parent
e492be3195
commit
02ee32bb0d
@ -106,17 +106,48 @@ AppearancePrefView::AppearancePrefView(const char* name,
|
|||||||
colorsPopUp);
|
colorsPopUp);
|
||||||
fColorField->SetEnabled(false);
|
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)
|
BLayoutBuilder::Group<>(this)
|
||||||
.SetInsets(5, 5, 5, 5)
|
.SetInsets(5, 5, 5, 5)
|
||||||
.AddGrid(5, 5)
|
.AddGrid(5, 5)
|
||||||
.Add(fFont->CreateLabelLayoutItem(), 0, 0)
|
.AddTextControl(fTabTitle, 0, 0, B_ALIGN_RIGHT)
|
||||||
.Add(fFont->CreateMenuBarLayoutItem(), 1, 0)
|
.AddTextControl(fWindowTitle, 0, 1, B_ALIGN_RIGHT)
|
||||||
.Add(fFontSize->CreateLabelLayoutItem(), 0, 1)
|
.Add(fFont->CreateLabelLayoutItem(), 0, 2)
|
||||||
.Add(fFontSize->CreateMenuBarLayoutItem(), 1, 1)
|
.Add(fFont->CreateMenuBarLayoutItem(), 1, 2)
|
||||||
.Add(fColorSchemaField->CreateLabelLayoutItem(), 0, 2)
|
.Add(fFontSize->CreateLabelLayoutItem(), 0, 3)
|
||||||
.Add(fColorSchemaField->CreateMenuBarLayoutItem(), 1, 2)
|
.Add(fFontSize->CreateMenuBarLayoutItem(), 1, 3)
|
||||||
.Add(fColorField->CreateLabelLayoutItem(), 0, 3)
|
.Add(fColorSchemaField->CreateLabelLayoutItem(), 0, 4)
|
||||||
.Add(fColorField->CreateMenuBarLayoutItem(), 1, 3)
|
.Add(fColorSchemaField->CreateMenuBarLayoutItem(), 1, 4)
|
||||||
|
.Add(fColorField->CreateLabelLayoutItem(), 0, 5)
|
||||||
|
.Add(fColorField->CreateMenuBarLayoutItem(), 1, 5)
|
||||||
.End()
|
.End()
|
||||||
.AddGlue()
|
.AddGlue()
|
||||||
.Add(fColorControl = new BColorControl(BPoint(10, 10),
|
.Add(fColorControl = new BColorControl(BPoint(10, 10),
|
||||||
@ -128,6 +159,9 @@ AppearancePrefView::AppearancePrefView(const char* name,
|
|||||||
fColorField->SetAlignment(B_ALIGN_RIGHT);
|
fColorField->SetAlignment(B_ALIGN_RIGHT);
|
||||||
fColorSchemaField->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->SetEnabled(false);
|
||||||
fColorControl->SetValue(
|
fColorControl->SetValue(
|
||||||
PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR));
|
PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR));
|
||||||
@ -158,6 +192,9 @@ AppearancePrefView::GetPreferredSize(float* _width, float* _height)
|
|||||||
void
|
void
|
||||||
AppearancePrefView::Revert()
|
AppearancePrefView::Revert()
|
||||||
{
|
{
|
||||||
|
fTabTitle->SetText(PrefHandler::Default()->getString(PREF_TAB_TITLE));
|
||||||
|
fWindowTitle->SetText(PrefHandler::Default()->getString(PREF_WINDOW_TITLE));
|
||||||
|
|
||||||
fWarnOnExit->SetValue(PrefHandler::Default()->getBool(
|
fWarnOnExit->SetValue(PrefHandler::Default()->getBool(
|
||||||
PREF_WARN_ON_EXIT));
|
PREF_WARN_ON_EXIT));
|
||||||
|
|
||||||
@ -175,6 +212,8 @@ AppearancePrefView::Revert()
|
|||||||
void
|
void
|
||||||
AppearancePrefView::AttachedToWindow()
|
AppearancePrefView::AttachedToWindow()
|
||||||
{
|
{
|
||||||
|
fTabTitle->SetTarget(this);
|
||||||
|
fWindowTitle->SetTarget(this);
|
||||||
fWarnOnExit->SetTarget(this);
|
fWarnOnExit->SetTarget(this);
|
||||||
|
|
||||||
fFontSize->Menu()->SetTargetForItems(this);
|
fFontSize->Menu()->SetTargetForItems(this);
|
||||||
@ -271,6 +310,30 @@ AppearancePrefView::MessageReceived(BMessage* msg)
|
|||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
BView::MessageReceived(msg);
|
BView::MessageReceived(msg);
|
||||||
return;
|
return;
|
||||||
|
@ -13,28 +13,31 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
const ulong MSG_HALF_FONT_CHANGED = 'mchf';
|
static const uint32 MSG_HALF_FONT_CHANGED = 'mchf';
|
||||||
const ulong MSG_HALF_SIZE_CHANGED = 'mchs';
|
static const uint32 MSG_HALF_SIZE_CHANGED = 'mchs';
|
||||||
const ulong MSG_FULL_FONT_CHANGED = 'mcff';
|
static const uint32 MSG_FULL_FONT_CHANGED = 'mcff';
|
||||||
const ulong MSG_FULL_SIZE_CHANGED = 'mcfs';
|
static const uint32 MSG_FULL_SIZE_CHANGED = 'mcfs';
|
||||||
const ulong MSG_COLOR_FIELD_CHANGED = 'mccf';
|
static const uint32 MSG_COLOR_FIELD_CHANGED = 'mccf';
|
||||||
const ulong MSG_COLOR_CHANGED = 'mcbc';
|
static const uint32 MSG_COLOR_CHANGED = 'mcbc';
|
||||||
const ulong MSG_COLOR_SCHEMA_CHANGED = 'mccs';
|
static const uint32 MSG_COLOR_SCHEMA_CHANGED = 'mccs';
|
||||||
|
|
||||||
const ulong MSG_WARN_ON_EXIT_CHANGED = 'mwec';
|
static const uint32 MSG_TAB_TITLE_SETTING_CHANGED = 'mtts';
|
||||||
const ulong MSG_COLS_CHANGED = 'mccl';
|
static const uint32 MSG_WINDOW_TITLE_SETTING_CHANGED = 'mwts';
|
||||||
const ulong MSG_ROWS_CHANGED = 'mcrw';
|
static const uint32 MSG_WARN_ON_EXIT_CHANGED = 'mwec';
|
||||||
const ulong MSG_HISTORY_CHANGED = 'mhst';
|
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;
|
struct color_schema;
|
||||||
|
class BCheckBox;
|
||||||
class BColorControl;
|
class BColorControl;
|
||||||
class BMenu;
|
class BMenu;
|
||||||
class BMenuField;
|
class BMenuField;
|
||||||
class BPopUpMenu;
|
class BPopUpMenu;
|
||||||
class BCheckBox;
|
class BTextControl;
|
||||||
|
|
||||||
|
|
||||||
class AppearancePrefView : public BGroupView {
|
class AppearancePrefView : public BGroupView {
|
||||||
@ -76,6 +79,9 @@ private:
|
|||||||
BMenuField* fColorField;
|
BMenuField* fColorField;
|
||||||
BColorControl* fColorControl;
|
BColorControl* fColorControl;
|
||||||
|
|
||||||
|
BTextControl* fTabTitle;
|
||||||
|
BTextControl* fWindowTitle;
|
||||||
|
|
||||||
BMessenger fTerminalMessenger;
|
BMessenger fTerminalMessenger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ Application Terminal :
|
|||||||
Globals.cpp
|
Globals.cpp
|
||||||
HistoryBuffer.cpp
|
HistoryBuffer.cpp
|
||||||
InlineInput.cpp
|
InlineInput.cpp
|
||||||
|
PatternEvaluator.cpp
|
||||||
PrefHandler.cpp
|
PrefHandler.cpp
|
||||||
PrefWindow.cpp
|
PrefWindow.cpp
|
||||||
Shell.cpp
|
Shell.cpp
|
||||||
@ -29,6 +30,7 @@ Application Terminal :
|
|||||||
TermScrollView.cpp
|
TermScrollView.cpp
|
||||||
TermView.cpp
|
TermView.cpp
|
||||||
TermWindow.cpp
|
TermWindow.cpp
|
||||||
|
TitlePlaceholderMapper.cpp
|
||||||
VTKeyTbl.c
|
VTKeyTbl.c
|
||||||
VTPrsTbl.c
|
VTPrsTbl.c
|
||||||
: be $(HAIKU_LOCALE_LIBS) tracker textencoding $(TARGET_LIBSUPC++)
|
: be $(HAIKU_LOCALE_LIBS) tracker textencoding $(TARGET_LIBSUPC++)
|
||||||
|
75
src/apps/terminal/PatternEvaluator.cpp
Normal file
75
src/apps/terminal/PatternEvaluator.cpp
Normal 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()
|
||||||
|
{
|
||||||
|
}
|
33
src/apps/terminal/PatternEvaluator.h
Normal file
33
src/apps/terminal/PatternEvaluator.h
Normal 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
|
@ -57,6 +57,8 @@ static const pref_defaults kTermDefaults[] = {
|
|||||||
{ PREF_GUI_LANGUAGE, "English"},
|
{ PREF_GUI_LANGUAGE, "English"},
|
||||||
{ PREF_IM_AWARE, "0"},
|
{ PREF_IM_AWARE, "0"},
|
||||||
|
|
||||||
|
{ PREF_TAB_TITLE, "%1d: %p" },
|
||||||
|
{ PREF_WINDOW_TITLE, "Terminal %i: %t" },
|
||||||
{ PREF_WARN_ON_EXIT, PREF_TRUE },
|
{ PREF_WARN_ON_EXIT, PREF_TRUE },
|
||||||
|
|
||||||
{ NULL, NULL},
|
{ NULL, NULL},
|
||||||
|
@ -59,6 +59,7 @@ main()
|
|||||||
TermApp::TermApp()
|
TermApp::TermApp()
|
||||||
: BApplication(TERM_SIGNATURE),
|
: BApplication(TERM_SIGNATURE),
|
||||||
fStartFullscreen(false),
|
fStartFullscreen(false),
|
||||||
|
fWindowTitleUserDefined(false),
|
||||||
fWindowNumber(-1),
|
fWindowNumber(-1),
|
||||||
fTermWindow(NULL),
|
fTermWindow(NULL),
|
||||||
fArgs(NULL)
|
fArgs(NULL)
|
||||||
@ -222,8 +223,10 @@ TermApp::ArgvReceived(int32 argc, char **argv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fArgs->Title() != NULL)
|
if (fArgs->Title() != NULL) {
|
||||||
fWindowTitle = fArgs->Title();
|
fWindowTitle = fArgs->Title();
|
||||||
|
fWindowTitleUserDefined = true;
|
||||||
|
}
|
||||||
|
|
||||||
fStartFullscreen = fArgs->FullScreen();
|
fStartFullscreen = fArgs->FullScreen();
|
||||||
}
|
}
|
||||||
@ -361,8 +364,8 @@ status_t
|
|||||||
TermApp::_MakeTermWindow(BRect &frame, uint32 workspaces)
|
TermApp::_MakeTermWindow(BRect &frame, uint32 workspaces)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
fTermWindow = new TermWindow(frame, fWindowTitle.String(), workspaces,
|
fTermWindow = new TermWindow(frame, fWindowTitle,
|
||||||
fArgs);
|
fWindowTitleUserDefined, fWindowNumber, workspaces, fArgs);
|
||||||
} catch (int error) {
|
} catch (int error) {
|
||||||
return (status_t)error;
|
return (status_t)error;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
@ -85,6 +85,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
bool fStartFullscreen;
|
bool fStartFullscreen;
|
||||||
BString fWindowTitle;
|
BString fWindowTitle;
|
||||||
|
bool fWindowTitleUserDefined;
|
||||||
int32 fWindowNumber;
|
int32 fWindowNumber;
|
||||||
|
|
||||||
BWindow* fTermWindow;
|
BWindow* fTermWindow;
|
||||||
|
@ -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_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
|
// Color type
|
||||||
enum {
|
enum {
|
||||||
TEXT_FOREGROUND_COLOR,
|
TEXT_FOREGROUND_COLOR,
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "TermConst.h"
|
#include "TermConst.h"
|
||||||
#include "TermScrollView.h"
|
#include "TermScrollView.h"
|
||||||
#include "TermView.h"
|
#include "TermView.h"
|
||||||
|
#include "TitlePlaceholderMapper.h"
|
||||||
|
|
||||||
|
|
||||||
const static int32 kMaxTabs = 6;
|
const static int32 kMaxTabs = 6;
|
||||||
@ -55,6 +56,7 @@ const static uint32 kCloseView = 'ClVw';
|
|||||||
const static uint32 kIncreaseFontSize = 'InFs';
|
const static uint32 kIncreaseFontSize = 'InFs';
|
||||||
const static uint32 kDecreaseFontSize = 'DcFs';
|
const static uint32 kDecreaseFontSize = 'DcFs';
|
||||||
const static uint32 kSetActiveTab = 'STab';
|
const static uint32 kSetActiveTab = 'STab';
|
||||||
|
const static uint32 kUpdateTitles = 'UPti';
|
||||||
|
|
||||||
|
|
||||||
#undef B_TRANSLATE_CONTEXT
|
#undef B_TRANSLATE_CONTEXT
|
||||||
@ -100,8 +102,7 @@ private:
|
|||||||
|
|
||||||
struct TermWindow::Session {
|
struct TermWindow::Session {
|
||||||
int32 id;
|
int32 id;
|
||||||
BString name;
|
Title title;
|
||||||
BString windowTitle;
|
|
||||||
TermViewContainerView* containerView;
|
TermViewContainerView* containerView;
|
||||||
|
|
||||||
Session(int32 id, TermViewContainerView* containerView)
|
Session(int32 id, TermViewContainerView* containerView)
|
||||||
@ -109,8 +110,9 @@ struct TermWindow::Session {
|
|||||||
id(id),
|
id(id),
|
||||||
containerView(containerView)
|
containerView(containerView)
|
||||||
{
|
{
|
||||||
name = B_TRANSLATE("Shell ");
|
title.title = B_TRANSLATE("Shell ");
|
||||||
name << id;
|
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)
|
Arguments* args)
|
||||||
:
|
:
|
||||||
BWindow(frame, title, B_DOCUMENT_WINDOW,
|
BWindow(frame, title, B_DOCUMENT_WINDOW,
|
||||||
B_CURRENT_WORKSPACE | B_QUIT_ON_WINDOW_CLOSE, workspaces),
|
B_CURRENT_WORKSPACE | B_QUIT_ON_WINDOW_CLOSE, workspaces),
|
||||||
fInitialTitle(title),
|
fWindowIndex(windowIndex),
|
||||||
|
fTitleUpdateRunner(this, BMessage(kUpdateTitles), 1000000),
|
||||||
fTabView(NULL),
|
fTabView(NULL),
|
||||||
fMenubar(NULL),
|
fMenubar(NULL),
|
||||||
fFilemenu(NULL),
|
fFilemenu(NULL),
|
||||||
@ -166,6 +170,12 @@ TermWindow::TermWindow(BRect frame, const char* title, uint32 workspaces,
|
|||||||
fMatchWord(false),
|
fMatchWord(false),
|
||||||
fFullScreen(false)
|
fFullScreen(false)
|
||||||
{
|
{
|
||||||
|
// apply the title settings
|
||||||
|
fTitle.title = title;
|
||||||
|
fTitle.pattern = title;
|
||||||
|
fTitle.patternUserDefined = isUserDefinedTitle;
|
||||||
|
_TitleSettingsChanged();
|
||||||
|
|
||||||
_InitWindow();
|
_InitWindow();
|
||||||
_AddTab(args);
|
_AddTab(args);
|
||||||
}
|
}
|
||||||
@ -189,15 +199,13 @@ TermWindow::~TermWindow()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TermWindow::SetSessionWindowTitle(TermView* termView, const char* title)
|
TermWindow::SetSessionTitle(TermView* termView, const char* title)
|
||||||
{
|
{
|
||||||
int32 index = _IndexOfTermView(termView);
|
int32 index = _IndexOfTermView(termView);
|
||||||
if (Session* session = (Session*)fSessions.ItemAt(index)) {
|
if (Session* session = (Session*)fSessions.ItemAt(index)) {
|
||||||
session->windowTitle = title;
|
session->title.pattern = title;
|
||||||
BTab* tab = fTabView->TabAt(index);
|
session->title.patternUserDefined = true;
|
||||||
tab->SetLabel(session->windowTitle.String());
|
_UpdateSessionTitle(index);
|
||||||
if (index == fTabView->Selection())
|
|
||||||
SetTitle(session->windowTitle.String());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,9 +213,7 @@ TermWindow::SetSessionWindowTitle(TermView* termView, const char* title)
|
|||||||
void
|
void
|
||||||
TermWindow::SessionChanged()
|
TermWindow::SessionChanged()
|
||||||
{
|
{
|
||||||
int32 index = fTabView->Selection();
|
_UpdateSessionTitle(fTabView->Selection());
|
||||||
if (Session* session = (Session*)fSessions.ItemAt(index))
|
|
||||||
SetTitle(session->windowTitle.String());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -509,6 +515,11 @@ TermWindow::MessageReceived(BMessage *message)
|
|||||||
fPrefWindow = NULL;
|
fPrefWindow = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSG_WINDOW_TITLE_SETTING_CHANGED:
|
||||||
|
case MSG_TAB_TITLE_SETTING_CHANGED:
|
||||||
|
_TitleSettingsChanged();
|
||||||
|
break;
|
||||||
|
|
||||||
case MENU_FIND_STRING:
|
case MENU_FIND_STRING:
|
||||||
if (!fFindPanel) {
|
if (!fFindPanel) {
|
||||||
fFindPanel = new FindWindow(this, fFindString, fFindSelection,
|
fFindPanel = new FindWindow(this, fFindString, fFindSelection,
|
||||||
@ -755,6 +766,10 @@ TermWindow::MessageReceived(BMessage *message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case kUpdateTitles:
|
||||||
|
_UpdateTitles();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BWindow::MessageReceived(message);
|
BWindow::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
@ -870,7 +885,6 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
|
|||||||
fTabView->SetScrollView(scrollView);
|
fTabView->SetScrollView(scrollView);
|
||||||
|
|
||||||
Session* session = new Session(_NewSessionID(), containerView);
|
Session* session = new Session(_NewSessionID(), containerView);
|
||||||
session->windowTitle = fInitialTitle;
|
|
||||||
fSessions.AddItem(session);
|
fSessions.AddItem(session);
|
||||||
|
|
||||||
BFont font;
|
BFont font;
|
||||||
@ -905,10 +919,6 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
|
|||||||
|
|
||||||
BTab* tab = new BTab;
|
BTab* tab = new BTab;
|
||||||
fTabView->AddTab(scrollView, tab);
|
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->SetScrollBar(scrollView->ScrollBar(B_VERTICAL));
|
||||||
view->SetMouseClipboard(gMouseClipboard);
|
view->SetMouseClipboard(gMouseClipboard);
|
||||||
view->SetEncoding(EncodingID(
|
view->SetEncoding(EncodingID(
|
||||||
@ -916,8 +926,10 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
|
|||||||
|
|
||||||
_SetTermColors(containerView);
|
_SetTermColors(containerView);
|
||||||
|
|
||||||
// TODO: No fTabView->Select(tab); ?
|
int32 tabIndex = fTabView->CountTabs() - 1;
|
||||||
fTabView->Select(fTabView->CountTabs() - 1);
|
fTabView->Select(tabIndex);
|
||||||
|
|
||||||
|
_UpdateSessionTitle(tabIndex);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// most probably out of memory. That's bad.
|
// most probably out of memory. That's bad.
|
||||||
// TODO: Should cleanup, I guess
|
// 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
|
int32
|
||||||
TermWindow::_NewSessionID()
|
TermWindow::_NewSessionID()
|
||||||
{
|
{
|
||||||
@ -1152,6 +1230,6 @@ CustomTermView::NotifyQuit(int32 reason)
|
|||||||
void
|
void
|
||||||
CustomTermView::SetTitle(const char* title)
|
CustomTermView::SetTitle(const char* title)
|
||||||
{
|
{
|
||||||
dynamic_cast<TermWindow*>(Window())->SetSessionWindowTitle(this, title);
|
dynamic_cast<TermWindow*>(Window())->SetSessionTitle(this, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define TERM_WINDOW_H
|
#define TERM_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <MessageRunner.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
@ -49,11 +50,12 @@ class TermViewContainerView;
|
|||||||
|
|
||||||
class TermWindow : public BWindow {
|
class TermWindow : public BWindow {
|
||||||
public:
|
public:
|
||||||
TermWindow(BRect frame, const char* title,
|
TermWindow(BRect frame, const BString& title,
|
||||||
|
bool isUserDefinedTitle, int32 windowIndex,
|
||||||
uint32 workspaces, Arguments* args);
|
uint32 workspaces, Arguments* args);
|
||||||
virtual ~TermWindow();
|
virtual ~TermWindow();
|
||||||
|
|
||||||
void SetSessionWindowTitle(TermView* termView,
|
void SetSessionTitle(TermView* termView,
|
||||||
const char* title);
|
const char* title);
|
||||||
void SessionChanged();
|
void SessionChanged();
|
||||||
|
|
||||||
@ -66,6 +68,12 @@ protected:
|
|||||||
virtual void FrameResized(float newWidth, float newHeight);
|
virtual void FrameResized(float newWidth, float newHeight);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Title {
|
||||||
|
BString title;
|
||||||
|
BString pattern;
|
||||||
|
bool patternUserDefined;
|
||||||
|
};
|
||||||
|
|
||||||
struct Session;
|
struct Session;
|
||||||
class TabView;
|
class TabView;
|
||||||
friend class TabView;
|
friend class TabView;
|
||||||
@ -92,10 +100,18 @@ private:
|
|||||||
void _CheckChildren();
|
void _CheckChildren();
|
||||||
void _ResizeView(TermView* view);
|
void _ResizeView(TermView* view);
|
||||||
|
|
||||||
|
void _TitleSettingsChanged();
|
||||||
|
void _UpdateTitles();
|
||||||
|
void _UpdateSessionTitle(int32 index);
|
||||||
|
|
||||||
int32 _NewSessionID();
|
int32 _NewSessionID();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fInitialTitle;
|
Title fTitle;
|
||||||
|
BString fSessionTitlePattern;
|
||||||
|
int32 fWindowIndex;
|
||||||
|
BMessageRunner fTitleUpdateRunner;
|
||||||
|
|
||||||
BList fSessions;
|
BList fSessions;
|
||||||
|
|
||||||
TabView* fTabView;
|
TabView* fTabView;
|
||||||
|
121
src/apps/terminal/TitlePlaceholderMapper.cpp
Normal file
121
src/apps/terminal/TitlePlaceholderMapper.cpp
Normal 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);
|
||||||
|
}
|
60
src/apps/terminal/TitlePlaceholderMapper.h
Normal file
60
src/apps/terminal/TitlePlaceholderMapper.h
Normal 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
|
Loading…
Reference in New Issue
Block a user