* 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

View File

@ -20,6 +20,7 @@ Application Terminal :
PatternEvaluator.cpp
PrefHandler.cpp
PrefWindow.cpp
SetTitleDialog.cpp
Shell.cpp
ShellParameters.cpp
SmartTabView.cpp

View File

@ -0,0 +1,139 @@
/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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()
{
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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

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_MOVE_TAB_LEFT = 'mvtl';
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
static const char* const PREF_HALF_FONT_FAMILY = "Half Font Family";

View File

@ -19,6 +19,7 @@
#include <Catalog.h>
#include <Clipboard.h>
#include <Dragger.h>
#include <LayoutUtils.h>
#include <Locale.h>
#include <Menu.h>
#include <MenuBar.h>
@ -40,6 +41,7 @@
#include "Globals.h"
#include "PrefWindow.h"
#include "PrefHandler.h"
#include "SetTitleDialog.h"
#include "ShellParameters.h"
#include "TermConst.h"
#include "TermScrollView.h"
@ -163,6 +165,7 @@ TermWindow::TermWindow(BRect frame, const BString& title,
fPrefWindow(NULL),
fFindPanel(NULL),
fSavedFrame(0, 0, -1, -1),
fSetTabTitleDialog(NULL),
fFindString(""),
fFindNextMenuItem(NULL),
fFindPreviousMenuItem(NULL),
@ -185,6 +188,8 @@ TermWindow::TermWindow(BRect frame, const BString& title,
TermWindow::~TermWindow()
{
_FinishTitleDialog();
if (fPrefWindow)
fPrefWindow->PostMessage(B_QUIT_REQUESTED);
@ -279,6 +284,8 @@ TermWindow::_CanClose(int32 index)
bool
TermWindow::QuitRequested()
{
_FinishTitleDialog();
if (!_CanClose(-1))
return false;
@ -688,6 +695,24 @@ TermWindow::MessageReceived(BMessage *message)
message->what == MSG_MOVE_TAB_LEFT ? -1 : 1, true);
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:
{
int32 index;
@ -942,6 +967,9 @@ TermWindow::_AddTab(Arguments* args, const BString& currentDirectory)
void
TermWindow::_RemoveTab(int32 index)
{
_FinishTitleDialog();
// always close to avoid confusion
if (fSessions.CountItems() > 1) {
if (!_CanClose(index))
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
TermWindow::_CheckChildren()
{
@ -1074,7 +1114,32 @@ void
TermWindow::TabDoubleClicked(SmartTabView* tabView, BPoint point, int32 index)
{
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 {
// not clicked on a tab -- create a new one
_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
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::_NewSessionID()
{

View File

@ -37,6 +37,7 @@
#include <Window.h>
#include "SmartTabView.h"
#include "SetTitleDialog.h"
#include "TermView.h"
@ -50,7 +51,7 @@ class TermViewContainerView;
class TermWindow : public BWindow, private SmartTabView::Listener,
private TermView::Listener {
private TermView::Listener, private SetTitleDialog::Listener {
public:
TermWindow(BRect frame, const BString& title,
bool isUserDefinedTitle, int32 windowIndex,
@ -85,6 +86,12 @@ private:
virtual void PreviousTermView(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:
struct Title {
BString title;
@ -93,13 +100,18 @@ private:
};
struct SessionID {
SessionID(int32 id);
SessionID(int32 id = -1);
SessionID(const BMessage& message,
const char* field);
status_t AddToMessage(BMessage& message,
const char* field) const;
bool operator==(const SessionID& other) const
{ return fID == other.fID; }
bool operator!=(const SessionID& other) const
{ return !(*this == other); }
private:
int32 fID;
};
@ -125,17 +137,21 @@ private:
bool move);
bool _CanClose(int32 index);
TermViewContainerView* _ActiveTermViewContainerView() const;
TermViewContainerView* _TermViewContainerViewAt(int32 index) const;
TermView* _ActiveTermView() const;
TermView* _TermViewAt(int32 index) const;
int32 _IndexOfTermView(TermView* termView) const;
Session* _SessionForID(const SessionID& sessionID) const;
void _CheckChildren();
void _ResizeView(TermView* view);
void _TitleSettingsChanged();
void _UpdateTitles();
void _UpdateSessionTitle(int32 index);
void _FinishTitleDialog();
SessionID _NewSessionID();
int32 _NewSessionIndex();
@ -150,7 +166,6 @@ private:
int32 fNextSessionID;
SmartTabView* fTabView;
TermView* fTermView;
BMenuBar* fMenubar;
BMenu* fFilemenu;
@ -166,6 +181,9 @@ private:
BRect fSavedFrame;
window_look fSavedLook;
SetTitleDialog* fSetTabTitleDialog;
SessionID fSetTabTitleSession;
// Saved search parameters
BString fFindString;
BMenuItem* fFindNextMenuItem;