* TermWindow does maintain a separate Session list instead of doing
nasty things with the tab view. * The tabs are named "Shell <number>" now, which is somewhat more useful than all being named "Terminal". This is similar to Konsole and we should probably also support setting the tab name by the user. Until Haiku supports persistent sessions, that is not really useful, though. * Shift-Left/Right iterates through the tabs, now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25960 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -82,6 +82,8 @@ const uint32 FULLSCREEN = 'fscr';
|
||||
const uint32 MSG_FONT_CHANGED = 'fntc';
|
||||
const uint32 SAVE_AS_DEFAULT = 'sadf';
|
||||
const uint32 MSG_CHECK_CHILDREN = 'ckch';
|
||||
const uint32 MSG_PREVIOUS_TAB = 'ptab';
|
||||
const uint32 MSG_NEXT_TAB = 'ntab';
|
||||
|
||||
const uint32 MSG_TERMINAL_BUFFER_CHANGED = 'bufc';
|
||||
const uint32 MSG_SET_TERMNAL_TITLE = 'sett';
|
||||
|
||||
@@ -1155,18 +1155,26 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
|
||||
|
||||
case B_LEFT_ARROW:
|
||||
if (rawChar == B_LEFT_ARROW) {
|
||||
if (mod & B_CONTROL_KEY)
|
||||
if (mod & B_SHIFT_KEY) {
|
||||
BMessage message(MSG_PREVIOUS_TAB);
|
||||
message.AddPointer("termView", this);
|
||||
Window()->PostMessage(&message);
|
||||
} else if (mod & B_CONTROL_KEY) {
|
||||
toWrite = CTRL_LEFT_ARROW_KEY_CODE;
|
||||
else
|
||||
} else
|
||||
toWrite = LEFT_ARROW_KEY_CODE;
|
||||
}
|
||||
break;
|
||||
|
||||
case B_RIGHT_ARROW:
|
||||
if (rawChar == B_RIGHT_ARROW) {
|
||||
if (mod & B_CONTROL_KEY)
|
||||
if (mod & B_SHIFT_KEY) {
|
||||
BMessage message(MSG_NEXT_TAB);
|
||||
message.AddPointer("termView", this);
|
||||
Window()->PostMessage(&message);
|
||||
} else if (mod & B_CONTROL_KEY) {
|
||||
toWrite = CTRL_RIGHT_ARROW_KEY_CODE;
|
||||
else
|
||||
} else
|
||||
toWrite = RIGHT_ARROW_KEY_CODE;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -87,6 +87,41 @@ private:
|
||||
};
|
||||
|
||||
|
||||
struct TermWindow::Session {
|
||||
int32 id;
|
||||
BString name;
|
||||
TermViewContainerView* containerView;
|
||||
|
||||
Session(int32 id, TermViewContainerView* containerView)
|
||||
:
|
||||
id(id),
|
||||
containerView(containerView)
|
||||
{
|
||||
name = "Shell ";
|
||||
name << id;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TermWindow::TabView : public SmartTabView {
|
||||
public:
|
||||
TabView(TermWindow* window, BRect frame, const char *name)
|
||||
:
|
||||
SmartTabView(frame, name),
|
||||
fWindow(window)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void RemoveAndDeleteTab(int32 index)
|
||||
{
|
||||
fWindow->_RemoveTab(index);
|
||||
}
|
||||
|
||||
private:
|
||||
TermWindow* fWindow;
|
||||
};
|
||||
|
||||
|
||||
TermWindow::TermWindow(BRect frame, const char* title, Arguments *args)
|
||||
: BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE),
|
||||
fTabView(NULL),
|
||||
@@ -124,6 +159,9 @@ TermWindow::~TermWindow()
|
||||
}
|
||||
|
||||
PrefHandler::DeleteDefault();
|
||||
|
||||
for (int32 i = 0; Session* session = (Session*)fSessions.ItemAt(i); i++)
|
||||
delete session;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +177,7 @@ TermWindow::_InitWindow()
|
||||
BRect textFrame = Bounds();
|
||||
textFrame.top = fMenubar->Bounds().bottom + 1.0;
|
||||
|
||||
fTabView = new SmartTabView(textFrame, "tab view");
|
||||
fTabView = new TabView(this, textFrame, "tab view");
|
||||
AddChild(fTabView);
|
||||
}
|
||||
|
||||
@@ -449,6 +487,21 @@ TermWindow::MessageReceived(BMessage *message)
|
||||
_CheckChildren();
|
||||
break;
|
||||
|
||||
case MSG_PREVIOUS_TAB:
|
||||
case MSG_NEXT_TAB:
|
||||
{
|
||||
TermView* termView;
|
||||
if (message->FindPointer("termView", (void**)&termView) == B_OK) {
|
||||
int32 count = fSessions.CountItems();
|
||||
int32 index = _IndexOfTermView(termView);
|
||||
if (count > 1 && index >= 0) {
|
||||
index += message->what == MSG_PREVIOUS_TAB ? -1 : 1;
|
||||
fTabView->Select((index + count) % count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kNewTab:
|
||||
if (fTabView->CountTabs() < kMaxTabs)
|
||||
_AddTab(NULL);
|
||||
@@ -606,12 +659,15 @@ TermWindow::_AddTab(Arguments *args)
|
||||
BScrollView *scrollView = new TermScrollView("scrollView",
|
||||
containerView, view);
|
||||
|
||||
Session* session = new Session(_NewSessionID(), containerView);
|
||||
fSessions.AddItem(session);
|
||||
|
||||
BTab *tab = new BTab;
|
||||
// TODO: Use a better name. For example, do like MacOsX's Terminal
|
||||
// and update the title using the last executed command ?
|
||||
// Or like Gnome's Terminal and use the current path ?
|
||||
fTabView->AddTab(scrollView, tab);
|
||||
tab->SetLabel("Terminal");
|
||||
tab->SetLabel(session->name.String());
|
||||
view->SetScrollBar(scrollView->ScrollBar(B_VERTICAL));
|
||||
|
||||
// Resize the vertical scrollbar to take the window gripping handle into account
|
||||
@@ -654,17 +710,21 @@ TermWindow::_AddTab(Arguments *args)
|
||||
// TODO: Should cleanup, I guess
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
TermWindow::_RemoveTab(int32 index)
|
||||
{
|
||||
if (fTabView->CountTabs() > 1)
|
||||
delete fTabView->RemoveTab(index);
|
||||
else
|
||||
if (fSessions.CountItems() > 1) {
|
||||
if (Session* session = (Session*)fSessions.RemoveItem(index)) {
|
||||
delete session;
|
||||
delete fTabView->RemoveTab(index);
|
||||
}
|
||||
} else
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
|
||||
|
||||
TermViewContainerView*
|
||||
TermWindow::_ActiveTermViewContainerView() const
|
||||
{
|
||||
@@ -675,11 +735,9 @@ TermWindow::_ActiveTermViewContainerView() const
|
||||
TermViewContainerView*
|
||||
TermWindow::_TermViewContainerViewAt(int32 index) const
|
||||
{
|
||||
// TODO: BAD HACK:
|
||||
// We should probably use the observer api to tell
|
||||
// the various "tabs" when settings are changed. Fix this.
|
||||
BScrollView* scrollView = (BScrollView*)fTabView->ViewForTab(index);
|
||||
return scrollView ? (TermViewContainerView*)scrollView->Target() : NULL;
|
||||
if (Session* session = (Session*)fSessions.ItemAt(index))
|
||||
return session->containerView;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -718,16 +776,10 @@ TermWindow::_IndexOfTermView(TermView* termView) const
|
||||
void
|
||||
TermWindow::_CheckChildren()
|
||||
{
|
||||
// There seems to be no separate list of sessions, so we have to iterate
|
||||
// through the tabs.
|
||||
int32 count = fTabView->CountTabs();
|
||||
int32 count = fSessions.CountItems();
|
||||
for (int32 i = count - 1; i >= 0; i--) {
|
||||
// get the term view
|
||||
TermView* termView = _TermViewAt(i);
|
||||
if (!termView)
|
||||
continue;
|
||||
|
||||
termView->CheckShellGone();
|
||||
Session* session = (Session*)fSessions.ItemAt(i);
|
||||
session->containerView->GetTermView()->CheckShellGone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,6 +839,29 @@ TermWindow::_BuildWindowSizeMenu(BMenu *menu)
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
TermWindow::_NewSessionID()
|
||||
{
|
||||
for (int32 id = 1; ; id++) {
|
||||
bool used = false;
|
||||
|
||||
for (int32 i = 0;
|
||||
Session* session = (Session*)fSessions.ItemAt(i); i++) {
|
||||
if (id == session->id) {
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!used)
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
// CustomTermView
|
||||
CustomTermView::CustomTermView(int32 rows, int32 columns, int32 argc, const char **argv, int32 historySize)
|
||||
:
|
||||
|
||||
@@ -57,6 +57,10 @@ protected:
|
||||
virtual void MenusBeginning();
|
||||
|
||||
private:
|
||||
struct Session;
|
||||
class TabView;
|
||||
friend class TabView;
|
||||
|
||||
void _SetTermColors(TermViewContainerView *termView);
|
||||
void _InitWindow();
|
||||
void _SetupMenu();
|
||||
@@ -73,10 +77,13 @@ private:
|
||||
void _CheckChildren();
|
||||
void _ResizeView(TermView *view);
|
||||
void _BuildWindowSizeMenu(BMenu *menu);
|
||||
int32 _NewSessionID();
|
||||
|
||||
BList fSessions;
|
||||
|
||||
SmartTabView *fTabView;
|
||||
TabView *fTabView;
|
||||
TermView *fTermView;
|
||||
|
||||
|
||||
BMenuBar *fMenubar;
|
||||
BMenu *fFilemenu;
|
||||
BMenu *fEditmenu;
|
||||
|
||||
Reference in New Issue
Block a user