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
This commit is contained in:
Ingo Weinhold 2010-11-18 17:16:56 +00:00
parent df942b3eb1
commit 92b0038ec0
5 changed files with 174 additions and 142 deletions

View File

@ -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';

View File

@ -5,11 +5,11 @@
* All rights reserved. Distributed under the terms of the MIT license.
*
* Authors:
* Stefano Ceccherini <stefano.ceccherini@gmail.com>
* Stefano Ceccherini, stefano.ceccherini@gmail.com
* Kian Duffy, myob@users.sourceforge.net
* Y.Hayakawa, hida@sawada.riec.tohoku.ac.jp
* Ingo Weinhold <ingo_weinhold@gmx.de>
* Clemens Zeidler <haiku@Clemens-Zeidler.de>
* 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)
{
}

View File

@ -1,16 +1,18 @@
/*
* Copyright 2001-2009, Haiku.
* Copyright 2001-2010, Haiku.
* Copyright (c) 2003-4 Kian Duffy <myob@users.sourceforge.net>
* Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
*
* Distributed under the terms of the MIT license.
* Authors:
* Stefano Ceccherini <stefano.ceccherini@gmail.com>
* 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 <Autolock.h>
#include <Messenger.h>
#include <String.h>
@ -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

View File

@ -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<TermWindow*>(Window())->SetSessionTitle(this, title);
}

View File

@ -37,6 +37,7 @@
#include <Window.h>
#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;