* Added bits and pieces to the model classes (Team, Thread, Image).

* Added beginnings of the team window. Currently only showing the thread list
  (not updated yet).
* Added application startup code and argument parsing.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31073 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-06-16 21:47:49 +00:00
parent 576813ea37
commit ac8b67130a
14 changed files with 987 additions and 51 deletions

View File

@ -0,0 +1,300 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <new>
#include <Application.h>
#include <Message.h>
#include "debug_utils.h"
#include "TeamDebugger.h"
extern const char* __progname;
const char* kProgramName = __progname;
static const char* const kDebuggerSignature
= "application/x-vnd.Haiku-Debugger";
static const char* kUsage =
"Usage: %s [ <options> ]\n"
" %s [ <options> ] <command line>\n"
" %s [ <options> ] --team <team>\n"
" %s [ <options> ] --thread <thread>\n"
"\n"
"The first form starts the debugger displaying a requester to choose a\n"
"running team to debug respectively to specify the program to run and\n"
"debug.\n"
"\n"
"The second form runs the given command line and attaches the debugger to\n"
"the new team. Unless specified otherwise the program will be stopped at\n"
"the beginning of its main() function.\n"
"\n"
"The third and fourth forms attach the debugger to a running team. The\n"
"fourth form additionally stops the specified thread.\n"
"\n"
"Options:\n"
" -h, --help - Print this usage info and exit.\n"
;
static void
print_usage_and_exit(bool error)
{
fprintf(error ? stderr : stdout, kUsage, kProgramName, kProgramName,
kProgramName, kProgramName);
exit(error ? 1 : 0);
}
struct Options {
int commandLineArgc;
const char* const* commandLineArgv;
team_id team;
thread_id thread;
Options()
:
commandLineArgc(0),
commandLineArgv(NULL),
team(-1),
thread(-1)
{
}
};
static bool
parse_arguments(int argc, const char* const* argv, bool noOutput,
Options& options)
{
printf("parse_arguments(): argc: %d\n", argc);
optind = 1;
while (true) {
static struct option sLongOptions[] = {
{ "help", no_argument, 0, 'h' },
{ "team", required_argument, 0, 't' },
{ "thread", required_argument, 0, 'T' },
{ 0, 0, 0, 0 }
};
opterr = 0; // don't print errors
int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL);
if (c == -1)
break;
switch (c) {
case 'h':
if (noOutput)
return false;
print_usage_and_exit(false);
break;
case 't':
{
options.team = strtol(optarg, NULL, 0);
if (options.team <= 0) {
if (noOutput)
return false;
print_usage_and_exit(true);
}
break;
}
case 'T':
{
options.thread = strtol(optarg, NULL, 0);
if (options.thread <= 0) {
if (noOutput)
return false;
print_usage_and_exit(true);
}
break;
}
default:
if (noOutput)
return false;
print_usage_and_exit(true);
break;
}
}
if (optind < argc) {
options.commandLineArgc = argc - optind;
options.commandLineArgv = argv + optind;
}
int exclusiveParams = 0;
if (options.team > 0)
exclusiveParams++;
if (options.thread > 0)
exclusiveParams++;
if (options.commandLineArgc > 0)
exclusiveParams++;
printf("exclusiveParams: %d\n", exclusiveParams);
if (exclusiveParams == 0) {
// TODO: Support!
if (noOutput)
return false;
fprintf(stderr, "Sorry, running without team/thread to debug not "
"supported yet.\n");
exit(1);
} else if (exclusiveParams != 1) {
if (noOutput)
return false;
print_usage_and_exit(true);
}
return true;
}
class Debugger : public BApplication {
public:
Debugger()
:
BApplication(kDebuggerSignature)
{
}
~Debugger()
{
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BApplication::MessageReceived(message);
break;
}
}
virtual void ReadyToRun()
{
}
virtual void ArgvReceived(int32 argc, char** argv)
{
Options options;
if (!parse_arguments(argc, argv, true, options))
{
printf("Debugger::ArgvReceived(): parsing args failed!\n");
return;
}
team_id team = options.team;
thread_id thread = options.thread;
bool stopInMain = false;
// If command line arguments were given, start the program.
if (options.commandLineArgc > 0) {
printf("loading program: \"%s\" ...\n", options.commandLineArgv[0]);
// TODO: What about the CWD?
thread = load_program(options.commandLineArgv,
options.commandLineArgc, false);
if (thread < 0) {
// TODO: Notify the user!
fprintf(stderr, "Error: Failed to load program \"%s\": %s\n",
options.commandLineArgv[0], strerror(thread));
return;
}
team = thread;
// main thread ID == team ID
stopInMain = true;
}
// If we've got
if (team < 0) {
printf("no team yet, getting thread info...\n");
thread_info threadInfo;
status_t error = get_thread_info(thread, &threadInfo);
if (error != B_OK) {
// TODO: Notify the user!
fprintf(stderr, "Error: Failed to get info for thread \"%ld\": "
"%s\n", thread, strerror(error));
return;
}
team = threadInfo.team;
}
printf("team: %ld, thread: %ld\n", team, thread);
TeamDebugger* debugger = _TeamDebuggerForTeam(team);
if (debugger != NULL) {
// TODO: Activate the respective window!
printf("There's already a debugger for team: %ld\n", team);
return;
}
debugger = new(std::nothrow) TeamDebugger;
if (debugger == NULL) {
// TODO: Notify the user!
fprintf(stderr, "Error: Out of memory!\n");
}
if (debugger->Init(team, thread, stopInMain) == B_OK)
{
printf("debugger for team %ld created and initialized successfully!\n", team);
fTeamDebuggers.Add(debugger);
}
else
delete debugger;
}
virtual bool QuitRequested()
{
// TODO:...
return true;
}
private:
typedef DoublyLinkedList<TeamDebugger> TeamDebuggerList;
private:
TeamDebugger* _TeamDebuggerForTeam(team_id teamID) const
{
for (TeamDebuggerList::ConstIterator it = fTeamDebuggers.GetIterator();
TeamDebugger* debugger = it.Next();) {
if (debugger->TeamID() == teamID)
return debugger;
}
return NULL;
}
private:
TeamDebuggerList fTeamDebuggers;
};
int
main(int argc, const char* const* argv)
{
// We test-parse the arguments here, so, when we're started from the
// terminal and there's an instance already running, we can print an error
// message to the terminal, if something's wrong with the arguments.
{
Options options;
parse_arguments(argc, argv, false, options);
}
Debugger app;
app.Run();
return 0;
}

View File

@ -0,0 +1,18 @@
resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku-Debugger";
resource app_version {
major = 1,
middle = 0,
minor = 0,
variety = B_APPV_BETA,
internal = 0,
short_info = "Debugger",
long_info = "Debugger ©2009 Haiku, Inc."
};
resource app_flags B_SINGLE_LAUNCH;
// TODO: Please give me a nice icon!

View File

@ -7,10 +7,11 @@
#include <image.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
class Image : public DoublyLinkedListLinkImpl<Image> {
class Image : public Referenceable, public DoublyLinkedListLinkImpl<Image> {
public:
Image(const image_info& imageInfo);
~Image();

View File

@ -3,11 +3,20 @@ SubDir HAIKU_TOP src apps debugger ;
CCFLAGS += -Werror ;
C++FLAGS += -Werror ;
UsePrivateHeaders kernel shared ;
UsePrivateHeaders interface kernel shared ;
UsePrivateSystemHeaders ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
local debugAnalyzerSources
= [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ;
SubDirHdrs [ FDirName $(HAIKU_TOP) src bin debug ] ;
SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ;
SubDirHdrs [ FDirName $(debugAnalyzerSources) util ] ;
Application Debugger :
debugger.cpp
Debugger.cpp
ElfFile.cpp
Image.cpp
@ -15,6 +24,13 @@ Application Debugger :
Team.cpp
Thread.cpp
# DebugAnalyzer:util
Variant.cpp
# gui/team_window
TeamWindow.cpp
ThreadListView.cpp
# DWARF
# attribute_classes.cpp
# AttributeValue.cpp
@ -24,7 +40,19 @@ Application Debugger :
# SourceLanguageInfo.cpp
# tag_names.cpp
: $(TARGET_LIBSUPC++) be
:
<nogrist>DebugAnalyzer_gui_table.o
<bin>debug_utils.a
libcolumnlistview.a
$(TARGET_LIBSTDC++)
be
: Debugger.rdef
;
SEARCH on [ FGristFiles Variant.cpp ]
= [ FDirName $(debugAnalyzerSources) util ] ;
HaikuSubInclude gui running_teams_window ;

View File

@ -8,6 +8,9 @@
#include <new>
// #pragma mark - Team
Team::Team(team_id teamID)
:
fID(teamID)
@ -18,10 +21,10 @@ Team::Team(team_id teamID)
Team::~Team()
{
while (Image* image = fImages.RemoveHead())
delete image;
image->RemoveReference();
while (Thread* thread = fThreads.RemoveHead())
delete thread;
thread->RemoveReference();
}
@ -43,6 +46,7 @@ void
Team::AddThread(Thread* thread)
{
fThreads.Add(thread);
_NotifyThreadAdded(thread);
}
@ -73,6 +77,7 @@ void
Team::RemoveThread(Thread* thread)
{
fThreads.Remove(thread);
_NotifyThreadRemoved(thread);
}
@ -84,7 +89,7 @@ Team::RemoveThread(thread_id threadID)
return false;
RemoveThread(thread);
delete thread;
thread->RemoveReference();
return true;
}
@ -102,10 +107,18 @@ Team::ThreadByID(thread_id threadID) const
}
const ThreadList&
Team::Threads() const
{
return fThreads;
}
void
Team::AddImage(Image* image)
{
fImages.Add(image);
_NotifyImageAdded(image);
}
@ -135,6 +148,7 @@ void
Team::RemoveImage(Image* image)
{
fImages.Remove(image);
_NotifyImageRemoved(image);
}
@ -146,7 +160,7 @@ Team::RemoveImage(image_id imageID)
return false;
RemoveImage(image);
delete image;
image->RemoveReference();
return true;
}
@ -162,3 +176,95 @@ Team::ImageByID(image_id imageID) const
return NULL;
}
const ImageList&
Team::Images() const
{
return fImages;
}
void
Team::AddListener(Listener* listener)
{
fListeners.Add(listener);
}
void
Team::RemoveListener(Listener* listener)
{
fListeners.Remove(listener);
}
void
Team::_NotifyThreadAdded(Thread* thread)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->ThreadAdded(this, thread);
}
}
void
Team::_NotifyThreadRemoved(Thread* thread)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->ThreadRemoved(this, thread);
}
}
void
Team::_NotifyImageAdded(Image* image)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->ImageAdded(this, image);
}
}
void
Team::_NotifyImageRemoved(Image* image)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->ImageRemoved(this, image);
}
}
// #pragma mark - Listener
Team::Listener::~Listener()
{
}
void
Team::Listener::ThreadAdded(Team* team, Thread* thread)
{
}
void
Team::Listener::ThreadRemoved(Team* team, Thread* thread)
{
}
void
Team::Listener::ImageAdded(Team* team, Image* image)
{
}
void
Team::Listener::ImageRemoved(Team* team, Image* image)
{
}

View File

@ -12,6 +12,9 @@
class Team : public BLocker {
public:
class Listener;
public:
Team(team_id teamID);
~Team();
@ -29,6 +32,7 @@ public:
void RemoveThread(Thread* thread);
bool RemoveThread(thread_id threadID);
Thread* ThreadByID(thread_id threadID) const;
const ThreadList& Threads() const;
void AddImage(Image* image);
status_t AddImage(const image_info& imageInfo,
@ -36,12 +40,39 @@ public:
void RemoveImage(Image* image);
bool RemoveImage(image_id imageID);
Image* ImageByID(image_id imageID) const;
const ImageList& Images() const;
void AddListener(Listener* listener);
void RemoveListener(Listener* listener);
private:
typedef DoublyLinkedList<Listener> ListenerList;
private:
void _NotifyThreadAdded(Thread* thread);
void _NotifyThreadRemoved(Thread* thread);
void _NotifyImageAdded(Image* image);
void _NotifyImageRemoved(Image* image);
private:
team_id fID;
BString fName;
ThreadList fThreads;
ImageList fImages;
ListenerList fListeners;
};
class Team::Listener : public DoublyLinkedListLinkImpl<Team::Listener> {
public:
virtual ~Listener();
virtual void ThreadAdded(Team* team, Thread* thread);
virtual void ThreadRemoved(Team* team, Thread* thread);
virtual void ImageAdded(Team* team, Image* image);
virtual void ImageRemoved(Team* team, Image* image);
};
#endif // TEAM_H

View File

@ -9,6 +9,8 @@
#include <new>
#include <Message.h>
#include <AutoLocker.h>
#include "Team.h"
@ -16,12 +18,13 @@
TeamDebugger::TeamDebugger()
:
fLock("team debugger"),
BLooper("team debugger"),
fTeam(NULL),
fTeamID(-1),
fDebuggerPort(-1),
fNubPort(-1),
fDebugEventListener(-1),
fTeamWindow(NULL),
fTerminating(false)
{
}
@ -29,7 +32,7 @@ TeamDebugger::TeamDebugger()
TeamDebugger::~TeamDebugger()
{
AutoLocker<BLocker> locker(fLock);
AutoLocker<BLooper> locker(this);
fTerminating = true;
@ -46,22 +49,18 @@ TeamDebugger::~TeamDebugger()
status_t
TeamDebugger::Init(team_id teamID)
TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
{
fTeamID = teamID;
status_t error = fLock.InitCheck();
if (error != B_OK)
return error;
// check whether the team exists at all
team_info teamInfo;
error = get_team_info(fTeamID, &teamInfo);
status_t error = get_team_info(fTeamID, &teamInfo);
if (error != B_OK)
return error;
// create a team object
fTeam = new(std::nothrow) Team(fTeamID);
fTeam = new(std::nothrow) ::Team(fTeamID);
if (fTeam == NULL)
return B_NO_MEMORY;
@ -86,7 +85,7 @@ TeamDebugger::Init(team_id teamID)
// TODO: Set the debug event flags!
// get the initial state of the team
AutoLocker<Team> teamLocker(fTeam);
AutoLocker< ::Team> teamLocker(fTeam);
thread_info threadInfo;
int32 cookie = 0;
@ -113,10 +112,47 @@ TeamDebugger::Init(team_id teamID)
resume_thread(fDebugEventListener);
// run looper
thread_id looperThread = Run();
if (looperThread < 0)
return looperThread;
// create the team window
try {
fTeamWindow = TeamWindow::Create(fTeam, this);
} catch (...) {
// TODO: Notify the user!
fprintf(stderr, "Error: Failed to create team window!\n");
return B_NO_MEMORY;
}
fTeamWindow->Show();
// if requested, stop the given thread
if (threadID >= 0) {
if (stopInMain) {
// TODO: Set a temporary breakpoint in main and run the thread.
} else {
debug_thread(threadID);
// TODO: Superfluous, if the thread is already stopped.
}
}
return B_OK;
}
void
TeamDebugger::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BLooper::MessageReceived(message);
break;
}
}
/*static*/ status_t
TeamDebugger::_DebugEventListenerEntry(void* data)
{

View File

@ -6,19 +6,29 @@
#define TEAM_DEBUGGER_H
#include <debugger.h>
#include <Locker.h>
#include <Looper.h>
#include <util/DoublyLinkedList.h>
#include "TeamWindow.h"
class Team;
class TeamDebugger {
class TeamDebugger : public DoublyLinkedListLinkImpl<TeamDebugger>,
private BLooper, private TeamWindow::Listener {
public:
TeamDebugger();
~TeamDebugger();
status_t Init(team_id teamID);
status_t Init(team_id teamID, thread_id threadID,
bool stopInMain);
team_id TeamID() const { return fTeamID; }
private:
virtual void MessageReceived(BMessage* message);
private:
static status_t _DebugEventListenerEntry(void* data);
@ -28,12 +38,12 @@ private:
const debug_debugger_message_data& message);
private:
BLocker fLock;
Team* fTeam;
::Team* fTeam;
team_id fTeamID;
port_id fDebuggerPort;
port_id fNubPort;
thread_id fDebugEventListener;
TeamWindow* fTeamWindow;
volatile bool fTerminating;
};

View File

@ -8,10 +8,11 @@
#include <OS.h>
#include <String.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
class Thread : public DoublyLinkedListLinkImpl<Thread> {
class Thread : public Referenceable, public DoublyLinkedListLinkImpl<Thread> {
public:
Thread(thread_id threadID);
~Thread();

View File

@ -1,27 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <stdio.h>
//#include "DwarfManager.h"
int
main(int argc, const char* const* argv)
{
if (argc != 2) {
fprintf(stderr, "Usage:...\n");
return 1;
}
const char* fileName = argv[1];
// DwarfManager manager;
// manager.LoadFile(fileName);
// manager.FinishLoading();
(void)fileName;
return 0;
}

View File

@ -0,0 +1,111 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "TeamWindow.h"
#include <GroupLayoutBuilder.h>
#include <Message.h>
#include <TabView.h>
#include "Team.h"
#include "ThreadListView.h"
// #pragma mark - TeamWindow
TeamWindow::TeamWindow(::Team* team, Listener* listener)
:
BWindow(BRect(100, 100, 399, 299), _GetWindowTitle(team).String(),
B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS),
fTeam(team),
fListener(listener),
fTabView(NULL),
fThreadListView(NULL)
{
}
TeamWindow::~TeamWindow()
{
}
/*static*/ TeamWindow*
TeamWindow::Create(::Team* team, Listener* listener)
{
TeamWindow* self = new TeamWindow(team, listener);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
TeamWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BWindow::MessageReceived(message);
break;
}
}
bool
TeamWindow::QuitRequested()
{
return fListener->TeamWindowQuitRequested(this);
}
/*static*/ BString
TeamWindow::_GetWindowTitle(::Team* team)
{
BString name = team->Name();
if (team->ID() >= 0)
name << " (" << team->ID() << ")";
return name;
}
void
TeamWindow::_Init()
{
BGroupLayout* rootLayout = new BGroupLayout(B_VERTICAL);
SetLayout(rootLayout);
fTabView = new BTabView("tab view");
BGroupLayoutBuilder(rootLayout)
.Add(fTabView);
fTabView->AddTab(fThreadListView = ThreadListView::Create());
// fTabView->AddTab(fTeamsPage = new TeamsPage(this));
// fTabView->AddTab(fThreadsPage = new ThreadsPage(this));
fThreadListView->SetTeam(fTeam);
}
// #pragma mark - Listener
TeamWindow::Listener::~Listener()
{
}
bool
TeamWindow::Listener::TeamWindowQuitRequested(TeamWindow* window)
{
return true;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_WINDOW_H
#define TEAM_WINDOW_H
#include <String.h>
#include <Window.h>
class BTabView;
class Team;
class ThreadListView;
class TeamWindow : public BWindow {
public:
class Listener;
public:
TeamWindow(::Team* team, Listener* listener);
~TeamWindow();
static TeamWindow* Create(::Team* team, Listener* listener);
// throws
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
private:
static BString _GetWindowTitle(::Team* team);
void _Init();
private:
::Team* fTeam;
Listener* fListener;
BTabView* fTabView;
ThreadListView* fThreadListView;
};
class TeamWindow::Listener {
public:
virtual ~Listener();
virtual bool TeamWindowQuitRequested(TeamWindow* window);
};
#endif // TEAM_WINDOW_H

View File

@ -0,0 +1,223 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ThreadListView.h"
#include <stdio.h>
#include <new>
#include <Looper.h>
#include <Message.h>
#include <AutoLocker.h>
#include <ObjectList.h>
#include "table/TableColumns.h"
enum {
MSG_SYNC_THREAD_LIST = 'sytl'
};
// #pragma mark - ThreadsTableModel
class ThreadListView::ThreadsTableModel : public TableModel {
public:
ThreadsTableModel(Team* team)
:
fTeam(team)
{
Update();
}
~ThreadsTableModel()
{
fTeam = NULL;
Update();
}
bool Update()
{
for (int32 i = 0; Thread* thread = fThreads.ItemAt(i); i++)
thread->RemoveReference();
fThreads.MakeEmpty();
if (fTeam == NULL)
return true;
AutoLocker<Team> locker(fTeam);
for (ThreadList::ConstIterator it = fTeam->Threads().GetIterator();
Thread* thread = it.Next();) {
if (!fThreads.AddItem(thread))
return false;
thread->AddReference();
}
return true;
}
virtual int32 CountColumns() const
{
return 2;
}
virtual int32 CountRows() const
{
return fThreads.CountItems();
}
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, Variant& value)
{
Thread* thread = fThreads.ItemAt(rowIndex);
if (thread == NULL)
return false;
switch (columnIndex) {
case 0:
value.SetTo(thread->ID());
return true;
case 1:
value.SetTo(thread->Name(), VARIANT_DONT_COPY_DATA);
return true;
default:
return false;
}
}
Thread* ThreadAt(int32 index) const
{
return fThreads.ItemAt(index);
}
private:
Team* fTeam;
BObjectList<Thread> fThreads;
};
// #pragma mark - ThreadListView
ThreadListView::ThreadListView()
:
BGroupView(B_VERTICAL),
fTeam(NULL),
fThreadsTable(NULL),
fThreadsTableModel(NULL)
{
SetName("Threads");
}
ThreadListView::~ThreadListView()
{
SetTeam(NULL);
fThreadsTable->SetTableModel(NULL);
delete fThreadsTableModel;
}
/*static*/ ThreadListView*
ThreadListView::Create()
{
ThreadListView* self = new ThreadListView;
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
ThreadListView::SetTeam(Team* team)
{
if (team == fTeam)
return;
if (fTeam != NULL) {
fTeam->RemoveListener(this);
fThreadsTable->SetTableModel(NULL);
delete fThreadsTableModel;
fThreadsTableModel = NULL;
}
fTeam = team;
if (fTeam != NULL) {
fThreadsTableModel = new(std::nothrow) ThreadsTableModel(fTeam);
fThreadsTable->SetTableModel(fThreadsTableModel);
fThreadsTable->ResizeAllColumnsToPreferred();
fTeam->AddListener(this);
}
}
void
ThreadListView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_SYNC_THREAD_LIST:
if (fThreadsTableModel != NULL) {
fThreadsTable->SetTableModel(NULL);
fThreadsTableModel->Update();
fThreadsTable->SetTableModel(fThreadsTableModel);
}
break;
default:
BGroupView::MessageReceived(message);
break;
}
}
void
ThreadListView::ThreadAdded(Team* team, Thread* thread)
{
Looper()->PostMessage(MSG_SYNC_THREAD_LIST, this);
}
void
ThreadListView::ThreadRemoved(Team* team, Thread* thread)
{
Looper()->PostMessage(MSG_SYNC_THREAD_LIST, this);
}
void
ThreadListView::TableRowInvoked(Table* table, int32 rowIndex)
{
// if (fThreadsTableModel != NULL) {
// Thread* thread = fThreadsTableModel->ThreadAt(rowIndex);
// if (thread != NULL)
// fParent->OpenThreadWindow(thread);
// }
}
void
ThreadListView::_Init()
{
fThreadsTable = new Table("threads list", 0);
AddChild(fThreadsTable->ToView());
// columns
fThreadsTable->AddColumn(new Int32TableColumn(0, "ID", 40, 20, 1000,
B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT));
fThreadsTable->AddColumn(new StringTableColumn(1, "Name", 80, 40, 1000,
B_TRUNCATE_END, B_ALIGN_LEFT));
fThreadsTable->AddTableListener(this);
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef THREAD_LIST_VIEW_H
#define THREAD_LIST_VIEW_H
#include <GroupView.h>
#include "table/Table.h"
#include "Team.h"
class ThreadListView : public BGroupView, private Team::Listener,
private TableListener {
public:
ThreadListView();
~ThreadListView();
static ThreadListView* Create();
// throws
void SetTeam(Team* team);
virtual void MessageReceived(BMessage* message);
private:
class ThreadsTableModel;
private:
// Team::Listener
virtual void ThreadAdded(Team* team, Thread* thread);
virtual void ThreadRemoved(Team* team, Thread* thread);
// TableListener
virtual void TableRowInvoked(Table* table, int32 rowIndex);
void _Init();
private:
Team* fTeam;
Table* fThreadsTable;
ThreadsTableModel* fThreadsTableModel;
};
#endif // THREAD_LIST_VIEW_H