From 92b0038ec03c6184daa8588f01c7684aef0b002b Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 18 Nov 2010 17:16:56 +0000 Subject: [PATCH] Added a listener interface to TermView. This allowed to get rid of CustomTermView and of the messaging from view to window. It also simplified things in TermWindow. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39487 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/terminal/TermConst.h | 2 - src/apps/terminal/TermView.cpp | 116 +++++++++++++++---------- src/apps/terminal/TermView.h | 38 +++++++-- src/apps/terminal/TermWindow.cpp | 141 +++++++++++++------------------ src/apps/terminal/TermWindow.h | 19 ++++- 5 files changed, 174 insertions(+), 142 deletions(-) diff --git a/src/apps/terminal/TermConst.h b/src/apps/terminal/TermConst.h index ef372ac22a..651802539e 100644 --- a/src/apps/terminal/TermConst.h +++ b/src/apps/terminal/TermConst.h @@ -85,8 +85,6 @@ static const uint32 FULLSCREEN = 'fscr'; static const uint32 MSG_FONT_CHANGED = 'fntc'; static const uint32 SAVE_AS_DEFAULT = 'sadf'; static const uint32 MSG_CHECK_CHILDREN = 'ckch'; -static const uint32 MSG_PREVIOUS_TAB = 'ptab'; -static const uint32 MSG_NEXT_TAB = 'ntab'; static const uint32 MSG_REMOVE_RESIZE_VIEW_IF_NEEDED = 'rmrv'; static const uint32 MSG_TERMINAL_BUFFER_CHANGED = 'bufc'; static const uint32 MSG_SET_TERMNAL_TITLE = 'sett'; diff --git a/src/apps/terminal/TermView.cpp b/src/apps/terminal/TermView.cpp index 893b90ff86..099c28229c 100644 --- a/src/apps/terminal/TermView.cpp +++ b/src/apps/terminal/TermView.cpp @@ -5,11 +5,11 @@ * All rights reserved. Distributed under the terms of the MIT license. * * Authors: - * Stefano Ceccherini + * Stefano Ceccherini, stefano.ceccherini@gmail.com * Kian Duffy, myob@users.sourceforge.net * Y.Hayakawa, hida@sawada.riec.tohoku.ac.jp - * Ingo Weinhold - * Clemens Zeidler + * Ingo Weinhold, ingo_weinhold@gmx.de + * Clemens Zeidler, haiku@Clemens-Zeidler.de */ @@ -392,6 +392,9 @@ restrict_value(const Type& value, const Type& min, const Type& max) } +// #pragma mark - CharClassifier + + class TermView::CharClassifier : public TerminalCharClassifier { public: CharClassifier(const char* specialWordChars) @@ -420,13 +423,15 @@ private: }; -// #pragma mark - +// #pragma mark - TermView TermView::TermView(BRect frame, const ShellParameters& shellParameters, int32 historySize) - : BView(frame, "termview", B_FOLLOW_ALL, + : + BView(frame, "termview", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE), + fListener(NULL), fColumns(COLUMNS_DEFAULT), fRows(ROWS_DEFAULT), fEncoding(M_UTF8), @@ -446,8 +451,10 @@ TermView::TermView(BRect frame, const ShellParameters& shellParameters, TermView::TermView(int rows, int columns, const ShellParameters& shellParameters, int32 historySize) - : BView(BRect(0, 0, 0, 0), "termview", B_FOLLOW_ALL, + : + BView(BRect(0, 0, 0, 0), "termview", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE), + fListener(NULL), fColumns(columns), fRows(rows), fEncoding(M_UTF8), @@ -480,6 +487,7 @@ TermView::TermView(int rows, int columns, TermView::TermView(BMessage* archive) : BView(archive), + fListener(NULL), fColumns(COLUMNS_DEFAULT), fRows(ROWS_DEFAULT), fEncoding(M_UTF8), @@ -949,16 +957,6 @@ TermView::SetScrollBar(BScrollBar *scrollBar) } -void -TermView::SetTitle(const char *title) -{ - // TODO: Do something different in case we're a replicant, - // or in case we are inside a BTabView ? - if (Window()) - Window()->SetTitle(title); -} - - void TermView::Copy(BClipboard *clipboard) { @@ -1590,28 +1588,32 @@ TermView::KeyDown(const char *bytes, int32 numBytes) case B_LEFT_ARROW: if (rawChar == B_LEFT_ARROW) { - if (mod & B_SHIFT_KEY) { - BMessage message(MSG_PREVIOUS_TAB); - message.AddPointer("termView", this); - Window()->PostMessage(&message); + if ((mod & B_SHIFT_KEY) != 0) { + if (fListener != NULL) { + fListener->PreviousTermView(this, + (mod & B_COMMAND_KEY) != 0); + } return; - } else if ((mod & B_CONTROL_KEY) || (mod & B_COMMAND_KEY)) { + } + if ((mod & B_CONTROL_KEY) || (mod & B_COMMAND_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_SHIFT_KEY) { - BMessage message(MSG_NEXT_TAB); - message.AddPointer("termView", this); - Window()->PostMessage(&message); + if ((mod & B_SHIFT_KEY) != 0) { + if (fListener != NULL) { + fListener->NextTermView(this, + (mod & B_COMMAND_KEY) != 0); + } return; - } else if ((mod & B_CONTROL_KEY) || (mod & B_COMMAND_KEY)) { + } + if ((mod & B_CONTROL_KEY) || (mod & B_COMMAND_KEY)) toWrite = CTRL_RIGHT_ARROW_KEY_CODE; - } else + else toWrite = RIGHT_ARROW_KEY_CODE; } break; @@ -1951,8 +1953,10 @@ TermView::MessageReceived(BMessage *msg) case MSG_SET_TERMNAL_TITLE: { const char* title; - if (msg->FindString("title", &title) == B_OK) - SetTitle(title); + if (msg->FindString("title", &title) == B_OK) { + if (fListener != NULL) + fListener->SetTermViewTitle(this, title); + } break; } case MSG_REPORT_MOUSE_EVENT: @@ -1994,7 +1998,8 @@ TermView::MessageReceived(BMessage *msg) int32 reason; if (msg->FindInt32("reason", &reason) != B_OK) reason = 0; - NotifyQuit(reason); + if (fListener != NULL) + fListener->NotifyTermViewQuit(this, reason); break; } default: @@ -3001,26 +3006,16 @@ TermView::GetSelection(BString &str) } -void -TermView::NotifyQuit(int32 reason) -{ - // implemented in subclasses -} - - -void -TermView::CheckShellGone() +bool +TermView::CheckShellGone() const { if (!fShell) - return; + return false; // check, if the shell does still live pid_t pid = fShell->ProcessID(); team_info info; - if (get_team_info(pid, &info) == B_BAD_TEAM_ID) { - // the shell is gone - NotifyQuit(0); - } + return get_team_info(pid, &info) == B_BAD_TEAM_ID; } @@ -3293,3 +3288,34 @@ TermView::_CancelInputMethod() delete inlineInput; } + +// #pragma mark - Listener + + +TermView::Listener::~Listener() +{ +} + + +void +TermView::Listener::NotifyTermViewQuit(TermView* view, int32 reason) +{ +} + + +void +TermView::Listener::SetTermViewTitle(TermView* view, const char* title) +{ +} + + +void +TermView::Listener::PreviousTermView(TermView* view, bool move) +{ +} + + +void +TermView::Listener::NextTermView(TermView* view, bool move) +{ +} diff --git a/src/apps/terminal/TermView.h b/src/apps/terminal/TermView.h index b06243ec3c..c27bec8df6 100644 --- a/src/apps/terminal/TermView.h +++ b/src/apps/terminal/TermView.h @@ -1,16 +1,18 @@ /* - * Copyright 2001-2009, Haiku. + * Copyright 2001-2010, Haiku. * Copyright (c) 2003-4 Kian Duffy * Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai. * * Distributed under the terms of the MIT license. * Authors: - * Stefano Ceccherini + * Stefano Ceccherini, stefano.ceccherini@gmail.com * Kian Duffy, myob@users.sourceforge.net + * Ingo Weinhold, ingo_weinhold@gmx.de */ #ifndef TERMVIEW_H #define TERMVIEW_H + #include #include #include @@ -35,6 +37,9 @@ class TerminalBuffer; class Shell; class TermView : public BView { +public: + class Listener; + public: TermView(BRect frame, const ShellParameters& shellParameters, @@ -80,9 +85,6 @@ public: void SetMouseClipboard(BClipboard *); - virtual void SetTitle(const char* title); - virtual void NotifyQuit(int32 reason); - // edit functions void Copy(BClipboard* clipboard); void Paste(BClipboard* clipboard); @@ -95,13 +97,16 @@ public: bool matchCase, bool matchWord); void GetSelection(BString& string); - void CheckShellGone(); + bool CheckShellGone() const; void InitiateDrag(); void DisableResizeView(int32 disableCount = 1); static void AboutRequested(); + void SetListener(Listener* listener) + { fListener = listener; } + protected: virtual void AttachedToWindow(); virtual void DetachedFromWindow(); @@ -126,6 +131,9 @@ protected: BMessage* specifier, int32 form, const char* property); +private: + class CharClassifier; + private: // point and text offset conversion inline int32 _LineAt(float y); @@ -196,9 +204,9 @@ private: void _HandleInputMethodChanged(BMessage* message); void _HandleInputMethodLocationRequest(); void _CancelInputMethod(); -private: - class CharClassifier; +private: + Listener* fListener; Shell* fShell; BMessageRunner* fWinchRunner; @@ -279,4 +287,18 @@ private: }; +class TermView::Listener { +public: + virtual ~Listener(); + + // all hooks called in the window thread + virtual void NotifyTermViewQuit(TermView* view, + int32 reason); + virtual void SetTermViewTitle(TermView* view, + const char* title); + virtual void PreviousTermView(TermView* view, bool move); + virtual void NextTermView(TermView* view, bool move); +}; + + #endif // TERMVIEW_H diff --git a/src/apps/terminal/TermWindow.cpp b/src/apps/terminal/TermWindow.cpp index c256067551..b0ecc0ffb9 100644 --- a/src/apps/terminal/TermWindow.cpp +++ b/src/apps/terminal/TermWindow.cpp @@ -43,7 +43,6 @@ #include "ShellParameters.h" #include "TermConst.h" #include "TermScrollView.h" -#include "TermView.h" #include "TitlePlaceholderMapper.h" @@ -63,18 +62,6 @@ const static uint32 kUpdateTitles = 'UPti'; #define B_TRANSLATE_CONTEXT "Terminal TermWindow" -// #pragma mark - CustomTermView - - -class CustomTermView : public TermView { -public: - CustomTermView(int32 rows, int32 columns, - const ShellParameters& shellParameters, int32 historySize = 1000); - virtual void NotifyQuit(int32 reason); - virtual void SetTitle(const char *title); -}; - - // #pragma mark - TermViewContainerView @@ -213,18 +200,6 @@ TermWindow::~TermWindow() } -void -TermWindow::SetSessionTitle(TermView* termView, const char* title) -{ - int32 index = _IndexOfTermView(termView); - if (Session* session = (Session*)fSessions.ItemAt(index)) { - session->title.pattern = title; - session->title.patternUserDefined = true; - _UpdateSessionTitle(index); - } -} - - void TermWindow::SessionChanged() { @@ -702,21 +677,6 @@ 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 kSetActiveTab: { int32 index; @@ -894,11 +854,12 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory) ShellParameters shellParameters(argc, argv, currentDirectory); try { - CustomTermView* view = new CustomTermView( + TermView* view = new TermView( PrefHandler::Default()->getInt32(PREF_ROWS), PrefHandler::Default()->getInt32(PREF_COLS), shellParameters, PrefHandler::Default()->getInt32(PREF_HISTORY_SIZE)); + view->SetListener(this); TermViewContainerView* containerView = new TermViewContainerView(view); BScrollView* scrollView = new TermScrollView("scrollView", @@ -989,6 +950,22 @@ TermWindow::_RemoveTab(int32 index) } +void +TermWindow::_NavigateTab(int32 index, int32 direction, bool move) +{ + int32 count = fSessions.CountItems(); + if (count <= 1 || index < 0 || index >= count) + return; + + if (move) { + // TODO: Move the tab! + } else { + index += direction; + fTabView->Select((index + count) % count); + } +} + + TermViewContainerView* TermWindow::_ActiveTermViewContainerView() const { @@ -1043,7 +1020,8 @@ TermWindow::_CheckChildren() int32 count = fSessions.CountItems(); for (int32 i = count - 1; i >= 0; i--) { Session* session = (Session*)fSessions.ItemAt(i); - session->containerView->GetTermView()->CheckShellGone(); + if (session->containerView->GetTermView()->CheckShellGone()) + NotifyTermViewQuit(session->containerView->GetTermView(), 0); } } @@ -1119,6 +1097,44 @@ TermWindow::TabRightClicked(SmartTabView* tabView, BPoint point, int32 index) } +void +TermWindow::NotifyTermViewQuit(TermView* view, int32 reason) +{ + // Since the notification can come from the view, we send a message to + // ourselves to avoid deleting the caller synchronously. + BMessage message(kCloseView); + message.AddPointer("termView", view); + message.AddInt32("reason", reason); + PostMessage(&message); +} + + +void +TermWindow::SetTermViewTitle(TermView* view, const char* title) +{ + int32 index = _IndexOfTermView(view); + if (Session* session = (Session*)fSessions.ItemAt(index)) { + session->title.pattern = title; + session->title.patternUserDefined = true; + _UpdateSessionTitle(index); + } +} + + +void +TermWindow::PreviousTermView(TermView* view, bool move) +{ + _NavigateTab(_IndexOfTermView(view), -1, move); +} + + +void +TermWindow::NextTermView(TermView* view, bool move) +{ + _NavigateTab(_IndexOfTermView(view), 1, move); +} + + void TermWindow::_ResizeView(TermView *view) { @@ -1276,44 +1292,3 @@ TermWindow::_NewSessionIndex() return id; } } - - -// #pragma mark - - - -// CustomTermView -CustomTermView::CustomTermView(int32 rows, int32 columns, - const ShellParameters& shellParameters, int32 historySize) - : - TermView(rows, columns, shellParameters, historySize) -{ -} - - -void -CustomTermView::NotifyQuit(int32 reason) -{ - BWindow* window = Window(); - // TODO: If we got this from a view in a tab not currently selected, - // Window() will be NULL, as the view is detached. - // So we send the message to the first application window - // This isn't so cool, but should be safe, since a Terminal - // application has only one window, at least for now. - if (window == NULL) - window = be_app->WindowAt(0); - - if (window != NULL) { - BMessage message(kCloseView); - message.AddPointer("termView", this); - message.AddInt32("reason", reason); - window->PostMessage(&message); - } -} - - -void -CustomTermView::SetTitle(const char* title) -{ - dynamic_cast(Window())->SetSessionTitle(this, title); -} - diff --git a/src/apps/terminal/TermWindow.h b/src/apps/terminal/TermWindow.h index 778b4de2e6..2883ac7c81 100644 --- a/src/apps/terminal/TermWindow.h +++ b/src/apps/terminal/TermWindow.h @@ -37,6 +37,7 @@ #include #include "SmartTabView.h" +#include "TermView.h" class Arguments; @@ -45,19 +46,17 @@ class BMenu; class BMenuBar; class FindWindow; class PrefWindow; -class TermView; class TermViewContainerView; -class TermWindow : public BWindow, private SmartTabView::Listener { +class TermWindow : public BWindow, private SmartTabView::Listener, + private TermView::Listener { public: TermWindow(BRect frame, const BString& title, bool isUserDefinedTitle, int32 windowIndex, uint32 workspaces, Arguments* args); virtual ~TermWindow(); - void SetSessionTitle(TermView* termView, - const char* title); void SessionChanged(); protected: @@ -78,6 +77,14 @@ private: virtual void TabRightClicked(SmartTabView* tabView, BPoint point, int32 index); + // TermView::Listener + virtual void NotifyTermViewQuit(TermView* view, + int32 reason); + virtual void SetTermViewTitle(TermView* view, + const char* title); + virtual void PreviousTermView(TermView* view, bool move); + virtual void NextTermView(TermView* view, bool move); + private: struct Title { BString title; @@ -108,11 +115,15 @@ private: void _GetPreferredFont(BFont &font); status_t _DoPageSetup(); void _DoPrint(); + void _NewTab(); void _AddTab(Arguments* args, const BString& currentDirectory = BString()); void _RemoveTab(int32 index); + void _NavigateTab(int32 index, int32 direction, + bool move); + bool _CanClose(int32 index); TermViewContainerView* _ActiveTermViewContainerView() const; TermViewContainerView* _TermViewContainerViewAt(int32 index) const;