From 799a9a3449a0151626da9d454a892b5d34f17ff1 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 15 Jun 2008 02:18:31 +0000 Subject: [PATCH] * TermWindow does maintain a separate Session list instead of doing nasty things with the tab view. * The tabs are named "Shell " 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 --- src/apps/terminal/TermConst.h | 2 + src/apps/terminal/TermView.cpp | 16 +++-- src/apps/terminal/TermWindow.cpp | 117 +++++++++++++++++++++++++------ src/apps/terminal/TermWindow.h | 11 ++- 4 files changed, 119 insertions(+), 27 deletions(-) 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;