* Added SetTitleDialog, a dialog to edit a tab/window title.

* Use the dialog to open the tab title. Opened on double-click on the tab.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39497 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-11-19 11:49:23 +00:00
parent b647673227
commit 135f173dce
6 changed files with 329 additions and 4 deletions
+1
View File
@@ -20,6 +20,7 @@ Application Terminal :
PatternEvaluator.cpp PatternEvaluator.cpp
PrefHandler.cpp PrefHandler.cpp
PrefWindow.cpp PrefWindow.cpp
SetTitleDialog.cpp
Shell.cpp Shell.cpp
ShellParameters.cpp ShellParameters.cpp
SmartTabView.cpp SmartTabView.cpp
+139
View File
@@ -0,0 +1,139 @@
/*
* Copyright 2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "SetTitleDialog.h"
#include <Button.h>
#include <Catalog.h>
#include <LayoutBuilder.h>
#include <TextControl.h>
static const uint32 kMessageOK = 'okok';
static const uint32 kMessageDefault = 'dflt';
static const uint32 kMessageTitleChanged = 'chng';
#undef B_TRANSLATE_CONTEXT
#define B_TRANSLATE_CONTEXT "Terminal SetTitleWindow"
// #pragma mark - SetTitleDialog
SetTitleDialog::SetTitleDialog(const char* dialogTitle, const char* label,
const char* toolTip)
:
BWindow(BRect(0, 0, 0, 0), dialogTitle, B_BORDERED_WINDOW_LOOK,
B_FLOATING_APP_WINDOW_FEEL,
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fListener(NULL),
fTitle(),
fTitleUserDefined(false)
{
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(10, 10, 10, 10)
.Add(fTitleTextControl = new BTextControl("title", label, "", NULL))
.AddGroup(B_HORIZONTAL)
.Add(fDefaultButton = new BButton("defaultButton",
B_TRANSLATE("Use default"), new BMessage(kMessageDefault)))
.AddGlue()
.Add(fCancelButton = new BButton("cancelButton",
B_TRANSLATE("Cancel"), new BMessage(B_QUIT_REQUESTED)))
.Add(fOKButton = new BButton("okButton", B_TRANSLATE("OK"),
new BMessage(kMessageOK)));
fTitleTextControl->SetToolTip(toolTip);
fOKButton->MakeDefault(true);
UpdateSizeLimits();
// as a courtesy to our creator, who might want to place us
}
SetTitleDialog::~SetTitleDialog()
{
if (fListener != NULL) {
// reset to old title
fListener->TitleChanged(this, fOldTitle, fOldTitleUserDefined);
Listener* listener = fListener;
fListener = NULL;
listener->SetTitleDialogDone(this);
}
}
void
SetTitleDialog::Go(const BString& title, bool titleUserDefined,
Listener* listener)
{
fTitle = fOldTitle = title;
fTitleUserDefined = fOldTitleUserDefined = titleUserDefined;
fDefaultButton->SetEnabled(titleUserDefined);
fTitleTextControl->SetText(fTitle);
fTitleTextControl->SetModificationMessage(
new BMessage(kMessageTitleChanged));
fTitleTextControl->MakeFocus(true);
fListener = listener;
Show();
}
void
SetTitleDialog::Finish()
{
if (Listener* listener = fListener) {
fListener = NULL;
listener->SetTitleDialogDone(this);
}
PostMessage(B_QUIT_REQUESTED);
}
void
SetTitleDialog::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMessageDefault:
if (fListener != NULL)
fListener->TitleChanged(this, BString(), false);
// We're done now, fall through...
case kMessageOK:
Finish();
break;
case kMessageTitleChanged:
fTitle = fTitleTextControl->Text();
fTitleUserDefined = true;
fDefaultButton->SetEnabled(true);
if (fListener != NULL)
fListener->TitleChanged(this, fTitle, fTitleUserDefined);
break;
default:
BWindow::MessageReceived(message);
break;
}
}
// #pragma mark - SetTitleDialog
SetTitleDialog::Listener::~Listener()
{
}
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright 2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef SET_TITLE_DIALOG_H
#define SET_TITLE_DIALOG_H
#include <String.h>
#include <Window.h>
class BButton;
class BTextControl;
class SetTitleDialog : public BWindow {
public:
class Listener;
public:
SetTitleDialog(const char* dialogTitle,
const char* label, const char* toolTip);
virtual ~SetTitleDialog();
void Go(const BString& title, bool titleUserDefined,
Listener* listener);
void Finish();
// window must be locked
virtual void MessageReceived(BMessage* message);
private:
Listener* fListener;
BTextControl* fTitleTextControl;
BButton* fOKButton;
BButton* fCancelButton;
BButton* fDefaultButton;
BString fOldTitle;
BString fTitle;
bool fOldTitleUserDefined;
bool fTitleUserDefined;
};
class SetTitleDialog::Listener {
public:
virtual ~Listener();
// hooks called in the dialog thread with the window locked
virtual void TitleChanged(SetTitleDialog* dialog,
const BString& title,
bool titleUserDefined) = 0;
virtual void SetTitleDialogDone(SetTitleDialog* dialog) = 0;
};
#endif // SET_TITLE_DIALOG_H
+2
View File
@@ -93,6 +93,8 @@ static const uint32 MSG_REPORT_MOUSE_EVENT = 'mous';
static const uint32 MSG_SAVE_WINDOW_POSITION = 'swps'; static const uint32 MSG_SAVE_WINDOW_POSITION = 'swps';
static const uint32 MSG_MOVE_TAB_LEFT = 'mvtl'; static const uint32 MSG_MOVE_TAB_LEFT = 'mvtl';
static const uint32 MSG_MOVE_TAB_RIGHT = 'mvtr'; static const uint32 MSG_MOVE_TAB_RIGHT = 'mvtr';
static const uint32 MSG_TAB_TITLE_CHANGED = 'ttch';
static const uint32 MSG_WINDOW_TITLE_CHANGED = 'wtch';
// Preference Read/Write Keys // Preference Read/Write Keys
static const char* const PREF_HALF_FONT_FAMILY = "Half Font Family"; static const char* const PREF_HALF_FONT_FAMILY = "Half Font Family";
+108 -1
View File
@@ -19,6 +19,7 @@
#include <Catalog.h> #include <Catalog.h>
#include <Clipboard.h> #include <Clipboard.h>
#include <Dragger.h> #include <Dragger.h>
#include <LayoutUtils.h>
#include <Locale.h> #include <Locale.h>
#include <Menu.h> #include <Menu.h>
#include <MenuBar.h> #include <MenuBar.h>
@@ -40,6 +41,7 @@
#include "Globals.h" #include "Globals.h"
#include "PrefWindow.h" #include "PrefWindow.h"
#include "PrefHandler.h" #include "PrefHandler.h"
#include "SetTitleDialog.h"
#include "ShellParameters.h" #include "ShellParameters.h"
#include "TermConst.h" #include "TermConst.h"
#include "TermScrollView.h" #include "TermScrollView.h"
@@ -163,6 +165,7 @@ TermWindow::TermWindow(BRect frame, const BString& title,
fPrefWindow(NULL), fPrefWindow(NULL),
fFindPanel(NULL), fFindPanel(NULL),
fSavedFrame(0, 0, -1, -1), fSavedFrame(0, 0, -1, -1),
fSetTabTitleDialog(NULL),
fFindString(""), fFindString(""),
fFindNextMenuItem(NULL), fFindNextMenuItem(NULL),
fFindPreviousMenuItem(NULL), fFindPreviousMenuItem(NULL),
@@ -185,6 +188,8 @@ TermWindow::TermWindow(BRect frame, const BString& title,
TermWindow::~TermWindow() TermWindow::~TermWindow()
{ {
_FinishTitleDialog();
if (fPrefWindow) if (fPrefWindow)
fPrefWindow->PostMessage(B_QUIT_REQUESTED); fPrefWindow->PostMessage(B_QUIT_REQUESTED);
@@ -279,6 +284,8 @@ TermWindow::_CanClose(int32 index)
bool bool
TermWindow::QuitRequested() TermWindow::QuitRequested()
{ {
_FinishTitleDialog();
if (!_CanClose(-1)) if (!_CanClose(-1))
return false; return false;
@@ -688,6 +695,24 @@ TermWindow::MessageReceived(BMessage *message)
message->what == MSG_MOVE_TAB_LEFT ? -1 : 1, true); message->what == MSG_MOVE_TAB_LEFT ? -1 : 1, true);
break; break;
case MSG_TAB_TITLE_CHANGED:
{
// tab title changed message from SetTitleDialog
SessionID sessionID(*message, "session");
if (Session* session = _SessionForID(sessionID)) {
BString title;
if (message->FindString("title", &title) == B_OK) {
session->title.pattern = title;
session->title.patternUserDefined = true;
} else {
session->title.pattern.Truncate(0);
session->title.patternUserDefined = false;
}
_UpdateSessionTitle(fSessions.IndexOf(session));
}
break;
}
case kSetActiveTab: case kSetActiveTab:
{ {
int32 index; int32 index;
@@ -942,6 +967,9 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
void void
TermWindow::_RemoveTab(int32 index) TermWindow::_RemoveTab(int32 index)
{ {
_FinishTitleDialog();
// always close to avoid confusion
if (fSessions.CountItems() > 1) { if (fSessions.CountItems() > 1) {
if (!_CanClose(index)) if (!_CanClose(index))
return; return;
@@ -1032,6 +1060,18 @@ TermWindow::_IndexOfTermView(TermView* termView) const
} }
TermWindow::Session*
TermWindow::_SessionForID(const SessionID& sessionID) const
{
for (int32 i = 0; Session* session = (Session*)fSessions.ItemAt(i); i++) {
if (session->id == sessionID)
return session;
}
return NULL;
}
void void
TermWindow::_CheckChildren() TermWindow::_CheckChildren()
{ {
@@ -1074,7 +1114,32 @@ void
TermWindow::TabDoubleClicked(SmartTabView* tabView, BPoint point, int32 index) TermWindow::TabDoubleClicked(SmartTabView* tabView, BPoint point, int32 index)
{ {
if (index >= 0) { if (index >= 0) {
// TODO: Open the change title dialog! // If a dialog is active, finish it.
_FinishTitleDialog();
BString toolTip = BString(B_TRANSLATE(
"The pattern specifying the current tab title. The following "
"placeholders\n"
"can be used:\n")) << kTooTipSetTabTitlePlaceholders;
fSetTabTitleDialog = new SetTitleDialog(
B_TRANSLATE("Set tab title"), B_TRANSLATE("Tab title:"),
toolTip);
Session* session = (Session*)fSessions.ItemAt(index);
bool userDefined = session->title.patternUserDefined;
const BString& title = userDefined
? session->title.pattern : fSessionTitlePattern;
fSetTabTitleSession = session->id;
// place the dialog window directly under the tab, but keep it on screen
BPoint location = tabView->ConvertToScreen(
tabView->TabFrame(index).LeftBottom() + BPoint(0, 1));
BRect frame(fSetTabTitleDialog->Frame().OffsetToCopy(location));
BSize screenSize(BScreen(fSetTabTitleDialog).Frame().Size());
fSetTabTitleDialog->MoveTo(
BLayoutUtils::MoveIntoFrame(frame, screenSize).LeftTop());
fSetTabTitleDialog->Go(title, userDefined, this);
} else { } else {
// not clicked on a tab -- create a new one // not clicked on a tab -- create a new one
_NewTab(); _NewTab();
@@ -1139,6 +1204,33 @@ TermWindow::SetTermViewTitle(TermView* view, const char* title)
} }
void
TermWindow::TitleChanged(SetTitleDialog* dialog, const BString& title,
bool titleUserDefined)
{
if (dialog != fSetTabTitleDialog)
return;
BMessage message(MSG_TAB_TITLE_CHANGED);
fSetTabTitleSession.AddToMessage(message, "session");
if (titleUserDefined)
message.AddString("title", title);
PostMessage(&message);
}
void
TermWindow::SetTitleDialogDone(SetTitleDialog* dialog)
{
if (dialog == fSetTabTitleDialog) {
fSetTabTitleSession = SessionID();
fSetTabTitleDialog = NULL;
// assuming this is atomic
}
}
void void
TermWindow::PreviousTermView(TermView* view) TermWindow::PreviousTermView(TermView* view)
{ {
@@ -1285,6 +1377,21 @@ TermWindow::_UpdateSessionTitle(int32 index)
} }
void
TermWindow::_FinishTitleDialog()
{
SetTitleDialog* oldDialog = fSetTabTitleDialog;
if (oldDialog != NULL && oldDialog->Lock()) {
// might have been unset in the meantime, so recheck
if (fSetTabTitleDialog == oldDialog) {
oldDialog->Finish();
// this also unsets the variables
}
oldDialog->Unlock();
}
}
TermWindow::SessionID TermWindow::SessionID
TermWindow::_NewSessionID() TermWindow::_NewSessionID()
{ {
+21 -3
View File
@@ -37,6 +37,7 @@
#include <Window.h> #include <Window.h>
#include "SmartTabView.h" #include "SmartTabView.h"
#include "SetTitleDialog.h"
#include "TermView.h" #include "TermView.h"
@@ -50,7 +51,7 @@ class TermViewContainerView;
class TermWindow : public BWindow, private SmartTabView::Listener, class TermWindow : public BWindow, private SmartTabView::Listener,
private TermView::Listener { private TermView::Listener, private SetTitleDialog::Listener {
public: public:
TermWindow(BRect frame, const BString& title, TermWindow(BRect frame, const BString& title,
bool isUserDefinedTitle, int32 windowIndex, bool isUserDefinedTitle, int32 windowIndex,
@@ -85,6 +86,12 @@ private:
virtual void PreviousTermView(TermView* view); virtual void PreviousTermView(TermView* view);
virtual void NextTermView(TermView* view); virtual void NextTermView(TermView* view);
// SetTitleDialog::Listener
virtual void TitleChanged(SetTitleDialog* dialog,
const BString& title,
bool titleUserDefined);
virtual void SetTitleDialogDone(SetTitleDialog* dialog);
private: private:
struct Title { struct Title {
BString title; BString title;
@@ -93,13 +100,18 @@ private:
}; };
struct SessionID { struct SessionID {
SessionID(int32 id); SessionID(int32 id = -1);
SessionID(const BMessage& message, SessionID(const BMessage& message,
const char* field); const char* field);
status_t AddToMessage(BMessage& message, status_t AddToMessage(BMessage& message,
const char* field) const; const char* field) const;
bool operator==(const SessionID& other) const
{ return fID == other.fID; }
bool operator!=(const SessionID& other) const
{ return !(*this == other); }
private: private:
int32 fID; int32 fID;
}; };
@@ -125,17 +137,21 @@ private:
bool move); bool move);
bool _CanClose(int32 index); bool _CanClose(int32 index);
TermViewContainerView* _ActiveTermViewContainerView() const; TermViewContainerView* _ActiveTermViewContainerView() const;
TermViewContainerView* _TermViewContainerViewAt(int32 index) const; TermViewContainerView* _TermViewContainerViewAt(int32 index) const;
TermView* _ActiveTermView() const; TermView* _ActiveTermView() const;
TermView* _TermViewAt(int32 index) const; TermView* _TermViewAt(int32 index) const;
int32 _IndexOfTermView(TermView* termView) const; int32 _IndexOfTermView(TermView* termView) const;
Session* _SessionForID(const SessionID& sessionID) const;
void _CheckChildren(); void _CheckChildren();
void _ResizeView(TermView* view); void _ResizeView(TermView* view);
void _TitleSettingsChanged(); void _TitleSettingsChanged();
void _UpdateTitles(); void _UpdateTitles();
void _UpdateSessionTitle(int32 index); void _UpdateSessionTitle(int32 index);
void _FinishTitleDialog();
SessionID _NewSessionID(); SessionID _NewSessionID();
int32 _NewSessionIndex(); int32 _NewSessionIndex();
@@ -150,7 +166,6 @@ private:
int32 fNextSessionID; int32 fNextSessionID;
SmartTabView* fTabView; SmartTabView* fTabView;
TermView* fTermView;
BMenuBar* fMenubar; BMenuBar* fMenubar;
BMenu* fFilemenu; BMenu* fFilemenu;
@@ -166,6 +181,9 @@ private:
BRect fSavedFrame; BRect fSavedFrame;
window_look fSavedLook; window_look fSavedLook;
SetTitleDialog* fSetTabTitleDialog;
SessionID fSetTabTitleSession;
// Saved search parameters // Saved search parameters
BString fFindString; BString fFindString;
BMenuItem* fFindNextMenuItem; BMenuItem* fFindNextMenuItem;