diff --git a/src/apps/terminal/TermConst.h b/src/apps/terminal/TermConst.h index 5a65260f0a..266f340b48 100644 --- a/src/apps/terminal/TermConst.h +++ b/src/apps/terminal/TermConst.h @@ -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'; diff --git a/src/apps/terminal/TermView.cpp b/src/apps/terminal/TermView.cpp index 69287e5d25..ba6bb75cbf 100644 --- a/src/apps/terminal/TermView.cpp +++ b/src/apps/terminal/TermView.cpp @@ -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; diff --git a/src/apps/terminal/TermWindow.cpp b/src/apps/terminal/TermWindow.cpp index 6e4ab52741..a6adc9d729 100644 --- a/src/apps/terminal/TermWindow.cpp +++ b/src/apps/terminal/TermWindow.cpp @@ -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) : diff --git a/src/apps/terminal/TermWindow.h b/src/apps/terminal/TermWindow.h index c8f9c3268f..d66dbf9d15 100644 --- a/src/apps/terminal/TermWindow.h +++ b/src/apps/terminal/TermWindow.h @@ -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;