* 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:
@@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
@@ -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!
|
||||||
@@ -7,10 +7,11 @@
|
|||||||
|
|
||||||
#include <image.h>
|
#include <image.h>
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
class Image : public DoublyLinkedListLinkImpl<Image> {
|
class Image : public Referenceable, public DoublyLinkedListLinkImpl<Image> {
|
||||||
public:
|
public:
|
||||||
Image(const image_info& imageInfo);
|
Image(const image_info& imageInfo);
|
||||||
~Image();
|
~Image();
|
||||||
|
|||||||
@@ -3,11 +3,20 @@ SubDir HAIKU_TOP src apps debugger ;
|
|||||||
CCFLAGS += -Werror ;
|
CCFLAGS += -Werror ;
|
||||||
C++FLAGS += -Werror ;
|
C++FLAGS += -Werror ;
|
||||||
|
|
||||||
UsePrivateHeaders kernel shared ;
|
UsePrivateHeaders interface kernel shared ;
|
||||||
UsePrivateSystemHeaders ;
|
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 :
|
Application Debugger :
|
||||||
debugger.cpp
|
Debugger.cpp
|
||||||
ElfFile.cpp
|
ElfFile.cpp
|
||||||
|
|
||||||
Image.cpp
|
Image.cpp
|
||||||
@@ -15,6 +24,13 @@ Application Debugger :
|
|||||||
Team.cpp
|
Team.cpp
|
||||||
Thread.cpp
|
Thread.cpp
|
||||||
|
|
||||||
|
# DebugAnalyzer:util
|
||||||
|
Variant.cpp
|
||||||
|
|
||||||
|
# gui/team_window
|
||||||
|
TeamWindow.cpp
|
||||||
|
ThreadListView.cpp
|
||||||
|
|
||||||
# DWARF
|
# DWARF
|
||||||
# attribute_classes.cpp
|
# attribute_classes.cpp
|
||||||
# AttributeValue.cpp
|
# AttributeValue.cpp
|
||||||
@@ -24,7 +40,19 @@ Application Debugger :
|
|||||||
# SourceLanguageInfo.cpp
|
# SourceLanguageInfo.cpp
|
||||||
# tag_names.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 ;
|
HaikuSubInclude gui running_teams_window ;
|
||||||
|
|||||||
+110
-4
@@ -8,6 +8,9 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Team
|
||||||
|
|
||||||
|
|
||||||
Team::Team(team_id teamID)
|
Team::Team(team_id teamID)
|
||||||
:
|
:
|
||||||
fID(teamID)
|
fID(teamID)
|
||||||
@@ -18,10 +21,10 @@ Team::Team(team_id teamID)
|
|||||||
Team::~Team()
|
Team::~Team()
|
||||||
{
|
{
|
||||||
while (Image* image = fImages.RemoveHead())
|
while (Image* image = fImages.RemoveHead())
|
||||||
delete image;
|
image->RemoveReference();
|
||||||
|
|
||||||
while (Thread* thread = fThreads.RemoveHead())
|
while (Thread* thread = fThreads.RemoveHead())
|
||||||
delete thread;
|
thread->RemoveReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -43,6 +46,7 @@ void
|
|||||||
Team::AddThread(Thread* thread)
|
Team::AddThread(Thread* thread)
|
||||||
{
|
{
|
||||||
fThreads.Add(thread);
|
fThreads.Add(thread);
|
||||||
|
_NotifyThreadAdded(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -73,6 +77,7 @@ void
|
|||||||
Team::RemoveThread(Thread* thread)
|
Team::RemoveThread(Thread* thread)
|
||||||
{
|
{
|
||||||
fThreads.Remove(thread);
|
fThreads.Remove(thread);
|
||||||
|
_NotifyThreadRemoved(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -84,7 +89,7 @@ Team::RemoveThread(thread_id threadID)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
RemoveThread(thread);
|
RemoveThread(thread);
|
||||||
delete thread;
|
thread->RemoveReference();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,10 +107,18 @@ Team::ThreadByID(thread_id threadID) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const ThreadList&
|
||||||
|
Team::Threads() const
|
||||||
|
{
|
||||||
|
return fThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Team::AddImage(Image* image)
|
Team::AddImage(Image* image)
|
||||||
{
|
{
|
||||||
fImages.Add(image);
|
fImages.Add(image);
|
||||||
|
_NotifyImageAdded(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -135,6 +148,7 @@ void
|
|||||||
Team::RemoveImage(Image* image)
|
Team::RemoveImage(Image* image)
|
||||||
{
|
{
|
||||||
fImages.Remove(image);
|
fImages.Remove(image);
|
||||||
|
_NotifyImageRemoved(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -146,7 +160,7 @@ Team::RemoveImage(image_id imageID)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
RemoveImage(image);
|
RemoveImage(image);
|
||||||
delete image;
|
image->RemoveReference();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,3 +176,95 @@ Team::ImageByID(image_id imageID) const
|
|||||||
|
|
||||||
return NULL;
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
|
|
||||||
class Team : public BLocker {
|
class Team : public BLocker {
|
||||||
|
public:
|
||||||
|
class Listener;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Team(team_id teamID);
|
Team(team_id teamID);
|
||||||
~Team();
|
~Team();
|
||||||
@@ -29,6 +32,7 @@ public:
|
|||||||
void RemoveThread(Thread* thread);
|
void RemoveThread(Thread* thread);
|
||||||
bool RemoveThread(thread_id threadID);
|
bool RemoveThread(thread_id threadID);
|
||||||
Thread* ThreadByID(thread_id threadID) const;
|
Thread* ThreadByID(thread_id threadID) const;
|
||||||
|
const ThreadList& Threads() const;
|
||||||
|
|
||||||
void AddImage(Image* image);
|
void AddImage(Image* image);
|
||||||
status_t AddImage(const image_info& imageInfo,
|
status_t AddImage(const image_info& imageInfo,
|
||||||
@@ -36,12 +40,39 @@ public:
|
|||||||
void RemoveImage(Image* image);
|
void RemoveImage(Image* image);
|
||||||
bool RemoveImage(image_id imageID);
|
bool RemoveImage(image_id imageID);
|
||||||
Image* ImageByID(image_id imageID) const;
|
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:
|
private:
|
||||||
team_id fID;
|
team_id fID;
|
||||||
BString fName;
|
BString fName;
|
||||||
ThreadList fThreads;
|
ThreadList fThreads;
|
||||||
ImageList fImages;
|
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
|
#endif // TEAM_H
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include <Message.h>
|
||||||
|
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
@@ -16,12 +18,13 @@
|
|||||||
|
|
||||||
TeamDebugger::TeamDebugger()
|
TeamDebugger::TeamDebugger()
|
||||||
:
|
:
|
||||||
fLock("team debugger"),
|
BLooper("team debugger"),
|
||||||
fTeam(NULL),
|
fTeam(NULL),
|
||||||
fTeamID(-1),
|
fTeamID(-1),
|
||||||
fDebuggerPort(-1),
|
fDebuggerPort(-1),
|
||||||
fNubPort(-1),
|
fNubPort(-1),
|
||||||
fDebugEventListener(-1),
|
fDebugEventListener(-1),
|
||||||
|
fTeamWindow(NULL),
|
||||||
fTerminating(false)
|
fTerminating(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -29,7 +32,7 @@ TeamDebugger::TeamDebugger()
|
|||||||
|
|
||||||
TeamDebugger::~TeamDebugger()
|
TeamDebugger::~TeamDebugger()
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> locker(fLock);
|
AutoLocker<BLooper> locker(this);
|
||||||
|
|
||||||
fTerminating = true;
|
fTerminating = true;
|
||||||
|
|
||||||
@@ -46,22 +49,18 @@ TeamDebugger::~TeamDebugger()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugger::Init(team_id teamID)
|
TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
||||||
{
|
{
|
||||||
fTeamID = teamID;
|
fTeamID = teamID;
|
||||||
|
|
||||||
status_t error = fLock.InitCheck();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// check whether the team exists at all
|
// check whether the team exists at all
|
||||||
team_info teamInfo;
|
team_info teamInfo;
|
||||||
error = get_team_info(fTeamID, &teamInfo);
|
status_t error = get_team_info(fTeamID, &teamInfo);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// create a team object
|
// create a team object
|
||||||
fTeam = new(std::nothrow) Team(fTeamID);
|
fTeam = new(std::nothrow) ::Team(fTeamID);
|
||||||
if (fTeam == NULL)
|
if (fTeam == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -86,7 +85,7 @@ TeamDebugger::Init(team_id teamID)
|
|||||||
// TODO: Set the debug event flags!
|
// TODO: Set the debug event flags!
|
||||||
|
|
||||||
// get the initial state of the team
|
// get the initial state of the team
|
||||||
AutoLocker<Team> teamLocker(fTeam);
|
AutoLocker< ::Team> teamLocker(fTeam);
|
||||||
|
|
||||||
thread_info threadInfo;
|
thread_info threadInfo;
|
||||||
int32 cookie = 0;
|
int32 cookie = 0;
|
||||||
@@ -113,10 +112,47 @@ TeamDebugger::Init(team_id teamID)
|
|||||||
|
|
||||||
resume_thread(fDebugEventListener);
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamDebugger::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
default:
|
||||||
|
BLooper::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
TeamDebugger::_DebugEventListenerEntry(void* data)
|
TeamDebugger::_DebugEventListenerEntry(void* data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,19 +6,29 @@
|
|||||||
#define TEAM_DEBUGGER_H
|
#define TEAM_DEBUGGER_H
|
||||||
|
|
||||||
#include <debugger.h>
|
#include <debugger.h>
|
||||||
#include <Locker.h>
|
#include <Looper.h>
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
#include "TeamWindow.h"
|
||||||
|
|
||||||
|
|
||||||
class Team;
|
class Team;
|
||||||
|
|
||||||
|
|
||||||
class TeamDebugger {
|
class TeamDebugger : public DoublyLinkedListLinkImpl<TeamDebugger>,
|
||||||
|
private BLooper, private TeamWindow::Listener {
|
||||||
public:
|
public:
|
||||||
TeamDebugger();
|
TeamDebugger();
|
||||||
~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:
|
private:
|
||||||
static status_t _DebugEventListenerEntry(void* data);
|
static status_t _DebugEventListenerEntry(void* data);
|
||||||
@@ -28,12 +38,12 @@ private:
|
|||||||
const debug_debugger_message_data& message);
|
const debug_debugger_message_data& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLocker fLock;
|
::Team* fTeam;
|
||||||
Team* fTeam;
|
|
||||||
team_id fTeamID;
|
team_id fTeamID;
|
||||||
port_id fDebuggerPort;
|
port_id fDebuggerPort;
|
||||||
port_id fNubPort;
|
port_id fNubPort;
|
||||||
thread_id fDebugEventListener;
|
thread_id fDebugEventListener;
|
||||||
|
TeamWindow* fTeamWindow;
|
||||||
volatile bool fTerminating;
|
volatile bool fTerminating;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
class Thread : public DoublyLinkedListLinkImpl<Thread> {
|
class Thread : public Referenceable, public DoublyLinkedListLinkImpl<Thread> {
|
||||||
public:
|
public:
|
||||||
Thread(thread_id threadID);
|
Thread(thread_id threadID);
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* 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
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* 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
|
||||||
Reference in New Issue
Block a user