* Introduced interface UserInterface, which abstracts the user interface code.

* Added implementation GraphicalUserInterface for the current GUI.

TeamDebugger does no longer know about TeamWindow.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33594 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-10-15 09:47:24 +00:00
parent 4b6cb4f5ad
commit e3a631c0b4
43 changed files with 305 additions and 90 deletions
+10 -1
View File
@@ -19,6 +19,7 @@
#include "debug_utils.h" #include "debug_utils.h"
#include "GraphicalUserInterface.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "SettingsManager.h" #include "SettingsManager.h"
#include "TeamDebugger.h" #include "TeamDebugger.h"
@@ -261,7 +262,15 @@ printf("There's already a debugger for team: %ld\n", team);
return; return;
} }
debugger = new(std::nothrow) TeamDebugger(this, &fSettingsManager); UserInterface* userInterface = new(std::nothrow) GraphicalUserInterface;
if (userInterface == NULL) {
// TODO: Notify the user!
fprintf(stderr, "Error: Out of memory!\n");
}
Reference<UserInterface> userInterfaceReference(userInterface, true);
debugger = new(std::nothrow) TeamDebugger(this, userInterface,
&fSettingsManager);
if (debugger == NULL) { if (debugger == NULL) {
// TODO: Notify the user! // TODO: Notify the user!
fprintf(stderr, "Error: Out of memory!\n"); fprintf(stderr, "Error: Out of memory!\n");
+15 -7
View File
@@ -12,9 +12,11 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui model ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
@@ -94,11 +96,17 @@ Application Debugger :
LocatableFile.cpp LocatableFile.cpp
SourceFile.cpp SourceFile.cpp
# gui/model # user_interface
UserInterface.cpp
# user_interface/gui
GraphicalUserInterface.cpp
# user_interface/gui/model
VariablesViewState.cpp VariablesViewState.cpp
VariablesViewStateHistory.cpp VariablesViewStateHistory.cpp
# gui/team_window # user_interface/gui/team_window
BreakpointListView.cpp BreakpointListView.cpp
BreakpointsView.cpp BreakpointsView.cpp
ImageFunctionsView.cpp ImageFunctionsView.cpp
@@ -110,7 +118,7 @@ Application Debugger :
ThreadListView.cpp ThreadListView.cpp
VariablesView.cpp VariablesView.cpp
# gui/util # user_interface/gui/util
TargetAddressTableColumn.cpp TargetAddressTableColumn.cpp
# ids # ids
@@ -185,4 +193,4 @@ Application Debugger :
HaikuSubInclude arch x86 disasm ; HaikuSubInclude arch x86 disasm ;
HaikuSubInclude demangler ; HaikuSubInclude demangler ;
HaikuSubInclude dwarf ; HaikuSubInclude dwarf ;
HaikuSubInclude gui running_teams_window ; HaikuSubInclude user_interface gui running_teams_window ;
+19 -31
View File
@@ -11,7 +11,6 @@
#include <new> #include <new>
#include <Alert.h>
#include <Message.h> #include <Message.h>
#include <AutoLocker.h> #include <AutoLocker.h>
@@ -124,7 +123,8 @@ struct TeamDebugger::ImageHandlerHashDefinition {
// #pragma mark - TeamDebugger // #pragma mark - TeamDebugger
TeamDebugger::TeamDebugger(Listener* listener, SettingsManager* settingsManager) TeamDebugger::TeamDebugger(Listener* listener, UserInterface* userInterface,
SettingsManager* settingsManager)
: :
BLooper("team debugger"), BLooper("team debugger"),
fListener(listener), fListener(listener),
@@ -137,10 +137,11 @@ TeamDebugger::TeamDebugger(Listener* listener, SettingsManager* settingsManager)
fWorker(NULL), fWorker(NULL),
fBreakpointManager(NULL), fBreakpointManager(NULL),
fDebugEventListener(-1), fDebugEventListener(-1),
fTeamWindow(NULL), fUserInterface(userInterface),
fTerminating(false), fTerminating(false),
fKillTeamOnQuit(false) fKillTeamOnQuit(false)
{ {
fUserInterface->AcquireReference();
} }
@@ -164,13 +165,9 @@ TeamDebugger::~TeamDebugger()
if (fDebugEventListener >= 0) if (fDebugEventListener >= 0)
wait_for_thread(fDebugEventListener, NULL); wait_for_thread(fDebugEventListener, NULL);
// quit window // terminate UI
if (fTeamWindow != NULL) { fUserInterface->Terminate();
// TODO: This is not clean. If the window has been deleted we shouldn't fUserInterface->ReleaseReference();
// try to access it!
if (fTeamWindow->Lock())
fTeamWindow->Quit();
}
ThreadHandler* threadHandler = fThreadHandlers.Clear(true); ThreadHandler* threadHandler = fThreadHandlers.Clear(true);
while (threadHandler != NULL) { while (threadHandler != NULL) {
@@ -356,16 +353,14 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
if (looperThread < 0) if (looperThread < 0)
return looperThread; return looperThread;
// create the team window // init the UI
try { error = fUserInterface->Init(fTeam, this);
fTeamWindow = TeamWindow::Create(fTeam, this); if (error != B_OK) {
} catch (...) { ERROR("Error: Failed to init the UI: %s\n", strerror(error));
// TODO: Notify the user! return error;
ERROR("Error: Failed to create team window!\n");
return B_NO_MEMORY;
} }
fTeamWindow->Show(); fUserInterface->Show();
// if requested, stop the given thread // if requested, stop the given thread
if (threadID >= 0) { if (threadID >= 0) {
@@ -643,7 +638,7 @@ TeamDebugger::ClearBreakpointRequested(UserBreakpoint* breakpoint)
bool bool
TeamDebugger::TeamWindowQuitRequested() TeamDebugger::UserInterfaceQuitRequested()
{ {
AutoLocker< ::Team> locker(fTeam); AutoLocker< ::Team> locker(fTeam);
BString name(fTeam->Name()); BString name(fTeam->Name());
@@ -662,10 +657,10 @@ TeamDebugger::TeamWindowQuitRequested()
BString resumeLabel("Resume "); BString resumeLabel("Resume ");
resumeLabel << name; resumeLabel << name;
BAlert* alert = new BAlert("Quit Debugger", message.String(), int32 choice = fUserInterface->SynchronouslyAskUser("Quit Debugger",
killLabel.String(), "Cancel", resumeLabel.String()); message, killLabel, "Cancel", resumeLabel);
switch (alert->Go()) { switch (choice) {
case 0: case 0:
fKillTeamOnQuit = true; fKillTeamOnQuit = true;
break; break;
@@ -1291,15 +1286,8 @@ TeamDebugger::_NotifyUser(const char* title, const char* text,...)
vsnprintf(buffer, sizeof(buffer), text, args); vsnprintf(buffer, sizeof(buffer), text, args);
va_end(args); va_end(args);
// show the alert // notify the user
BAlert* alert = new(std::nothrow) BAlert(title, buffer, "OK", fUserInterface->NotifyUser(title, buffer, USER_NOTIFICATION_WARNING);
NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
if (alert != NULL)
alert->Go(NULL);
// TODO: We need to let the alert run asynchronously, but we shouldn't just
// create it and don't care anymore. Maybe an error window, which can
// display a list of errors would be the better choice.
} }
+6 -5
View File
@@ -13,8 +13,8 @@
#include "DebugEvent.h" #include "DebugEvent.h"
#include "Team.h" #include "Team.h"
#include "TeamWindow.h"
#include "ThreadHandler.h" #include "ThreadHandler.h"
#include "UserInterface.h"
#include "Worker.h" #include "Worker.h"
@@ -24,13 +24,14 @@ class SettingsManager;
class TeamDebugInfo; class TeamDebugInfo;
class TeamDebugger : public BLooper, private TeamWindow::Listener, class TeamDebugger : public BLooper, private UserInterfaceListener,
private JobListener, private Team::Listener { private JobListener, private Team::Listener {
public: public:
class Listener; class Listener;
public: public:
TeamDebugger(Listener* listener, TeamDebugger(Listener* listener,
UserInterface* userInterface,
SettingsManager* settingsManager); SettingsManager* settingsManager);
~TeamDebugger(); ~TeamDebugger();
@@ -42,7 +43,7 @@ public:
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
private: private:
// TeamWindow::Listener // UserInterfaceListener
virtual void FunctionSourceCodeRequested( virtual void FunctionSourceCodeRequested(
FunctionInstance* function); FunctionInstance* function);
virtual void ImageDebugInfoRequested(Image* image); virtual void ImageDebugInfoRequested(Image* image);
@@ -59,7 +60,7 @@ private:
virtual void ClearBreakpointRequested(target_addr_t address); virtual void ClearBreakpointRequested(target_addr_t address);
virtual void ClearBreakpointRequested( virtual void ClearBreakpointRequested(
UserBreakpoint* breakpoint); UserBreakpoint* breakpoint);
virtual bool TeamWindowQuitRequested(); virtual bool UserInterfaceQuitRequested();
// JobListener // JobListener
virtual void JobDone(Job* job); virtual void JobDone(Job* job);
@@ -133,7 +134,7 @@ private:
Worker* fWorker; Worker* fWorker;
BreakpointManager* fBreakpointManager; BreakpointManager* fBreakpointManager;
thread_id fDebugEventListener; thread_id fDebugEventListener;
TeamWindow* fTeamWindow; UserInterface* fUserInterface;
volatile bool fTerminating; volatile bool fTerminating;
bool fKillTeamOnQuit; bool fKillTeamOnQuit;
}; };
@@ -0,0 +1,23 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "UserInterface.h"
// #pragma mark - UserInterface
UserInterface::~UserInterface()
{
}
// #pragma mark - UserInterfaceListener
UserInterfaceListener::~UserInterfaceListener()
{
}
@@ -0,0 +1,84 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef USER_INTERFACE_H
#define USER_INTERFACE_H
#include <OS.h>
#include <Referenceable.h>
#include "Types.h"
class FunctionInstance;
class Image;
class StackFrame;
class Team;
class Thread;
class TypeComponentPath;
class UserBreakpoint;
class UserInterfaceListener;
class Variable;
enum user_notification_type {
USER_NOTIFICATION_INFO,
USER_NOTIFICATION_WARNING,
USER_NOTIFICATION_ERROR
};
class UserInterface : public BReferenceable {
public:
virtual ~UserInterface();
virtual status_t Init(Team* team,
UserInterfaceListener* listener) = 0;
virtual void Show() = 0;
virtual void Terminate() = 0;
// shut down the UI *now* -- no more user
// feedback
virtual void NotifyUser(const char* title,
const char* message,
user_notification_type type) = 0;
virtual int32 SynchronouslyAskUser(const char* title,
const char* message, const char* choice1,
const char* choice2, const char* choice3)
= 0;
};
class UserInterfaceListener {
public:
virtual ~UserInterfaceListener();
virtual void FunctionSourceCodeRequested(
FunctionInstance* function) = 0;
virtual void ImageDebugInfoRequested(Image* image) = 0;
virtual void StackFrameValueRequested(Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path) = 0;
// called with team locked
virtual void ThreadActionRequested(thread_id threadID,
uint32 action) = 0;
virtual void SetBreakpointRequested(target_addr_t address,
bool enabled) = 0;
virtual void SetBreakpointEnabledRequested(
UserBreakpoint* breakpoint,
bool enabled) = 0;
virtual void ClearBreakpointRequested(
target_addr_t address) = 0;
virtual void ClearBreakpointRequested(
UserBreakpoint* breakpoint) = 0;
// TODO: Consolidate those!
virtual bool UserInterfaceQuitRequested() = 0;
};
#endif // USER_INTERFACE_H
@@ -0,0 +1,99 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "GraphicalUserInterface.h"
#include <Alert.h>
#include "TeamWindow.h"
#include "Tracing.h"
GraphicalUserInterface::GraphicalUserInterface()
:
fTeamWindow(NULL)
{
}
GraphicalUserInterface::~GraphicalUserInterface()
{
}
status_t
GraphicalUserInterface::Init(Team* team, UserInterfaceListener* listener)
{
try {
fTeamWindow = TeamWindow::Create(team, listener);
} catch (...) {
// TODO: Notify the user!
ERROR("Error: Failed to create team window!\n");
return B_NO_MEMORY;
}
return B_OK;
}
void
GraphicalUserInterface::Show()
{
fTeamWindow->Show();
}
void
GraphicalUserInterface::Terminate()
{
// quit window
if (fTeamWindow != NULL) {
// TODO: This is not clean. If the window has been deleted we shouldn't
// try to access it!
if (fTeamWindow->Lock())
fTeamWindow->Quit();
}
}
void
GraphicalUserInterface::NotifyUser(const char* title, const char* message,
user_notification_type type)
{
// convert notification type to alert type
alert_type alertType;
switch (type) {
case USER_NOTIFICATION_INFO:
alertType = B_INFO_ALERT;
break;
case USER_NOTIFICATION_WARNING:
case USER_NOTIFICATION_ERROR:
alertType = B_WARNING_ALERT;
break;
}
BAlert* alert = new(std::nothrow) BAlert(title, message, "OK",
NULL, NULL, B_WIDTH_AS_USUAL, alertType);
if (alert != NULL)
alert->Go(NULL);
// TODO: We need to let the alert run asynchronously, but we shouldn't just
// create it and don't care anymore. Maybe an error window, which can
// display a list of errors would be the better choice.
}
int32
GraphicalUserInterface::SynchronouslyAskUser(const char* title,
const char* message, const char* choice1, const char* choice2,
const char* choice3)
{
BAlert* alert = new(std::nothrow) BAlert(title, message,
choice1, choice2, choice3);
if (alert == NULL)
return 0;
return alert->Go();
}
@@ -0,0 +1,39 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef GRAPHICAL_USER_INTERFACE_H
#define GRAPHICAL_USER_INTERFACE_H
#include "UserInterface.h"
class TeamWindow;
class GraphicalUserInterface : public UserInterface {
public:
GraphicalUserInterface();
virtual ~GraphicalUserInterface();
virtual status_t Init(Team* team,
UserInterfaceListener* listener);
virtual void Show();
virtual void Terminate();
// shut down the UI *now* -- no more user
// feedback
virtual void NotifyUser(const char* title,
const char* message,
user_notification_type type);
virtual int32 SynchronouslyAskUser(const char* title,
const char* message, const char* choice1,
const char* choice2, const char* choice3);
private:
TeamWindow* fTeamWindow;
};
#endif // GRAPHICAL_USER_INTERFACE_H
@@ -33,6 +33,7 @@
#include "StackTraceView.h" #include "StackTraceView.h"
#include "Tracing.h" #include "Tracing.h"
#include "TypeComponentPath.h" #include "TypeComponentPath.h"
#include "UserInterface.h"
#include "Variable.h" #include "Variable.h"
@@ -45,7 +46,7 @@ enum {
// #pragma mark - TeamWindow // #pragma mark - TeamWindow
TeamWindow::TeamWindow(::Team* team, Listener* listener) TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener)
: :
BWindow(BRect(100, 100, 899, 699), "Team", B_TITLED_WINDOW, BWindow(BRect(100, 100, 899, 699), "Team", B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
@@ -107,7 +108,7 @@ TeamWindow::~TeamWindow()
/*static*/ TeamWindow* /*static*/ TeamWindow*
TeamWindow::Create(::Team* team, Listener* listener) TeamWindow::Create(::Team* team, UserInterfaceListener* listener)
{ {
TeamWindow* self = new TeamWindow(team, listener); TeamWindow* self = new TeamWindow(team, listener);
@@ -265,7 +266,7 @@ TeamWindow::MessageReceived(BMessage* message)
bool bool
TeamWindow::QuitRequested() TeamWindow::QuitRequested()
{ {
return fListener->TeamWindowQuitRequested(); return fListener->UserInterfaceQuitRequested();
} }
@@ -968,11 +969,3 @@ TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint)
fSourceView->UserBreakpointChanged(breakpoint); fSourceView->UserBreakpointChanged(breakpoint);
fBreakpointsView->UserBreakpointChanged(breakpoint); fBreakpointsView->UserBreakpointChanged(breakpoint);
} }
// #pragma mark - Listener
TeamWindow::Listener::~Listener()
{
}
@@ -29,6 +29,7 @@ class RegistersView;
class SourceCode; class SourceCode;
class StackFrame; class StackFrame;
class UserBreakpoint; class UserBreakpoint;
class UserInterfaceListener;
class VariablesView; class VariablesView;
@@ -38,13 +39,12 @@ class TeamWindow : public BWindow, ThreadListView::Listener,
SourceView::Listener, VariablesView::Listener, Team::Listener, SourceView::Listener, VariablesView::Listener, Team::Listener,
Function::Listener, StackFrame::Listener { Function::Listener, StackFrame::Listener {
public: public:
class Listener; TeamWindow(::Team* team,
UserInterfaceListener* listener);
public:
TeamWindow(::Team* team, Listener* listener);
~TeamWindow(); ~TeamWindow();
static TeamWindow* Create(::Team* team, Listener* listener); static TeamWindow* Create(::Team* team,
UserInterfaceListener* listener);
// throws // throws
virtual void DispatchMessage(BMessage* message, virtual void DispatchMessage(BMessage* message,
@@ -148,7 +148,7 @@ private:
FunctionInstance* fActiveFunction; FunctionInstance* fActiveFunction;
SourceCode* fActiveSourceCode; SourceCode* fActiveSourceCode;
ActiveSourceObject fActiveSourceObject; ActiveSourceObject fActiveSourceObject;
Listener* fListener; UserInterfaceListener* fListener;
BTabView* fTabView; BTabView* fTabView;
BTabView* fLocalsTabView; BTabView* fLocalsTabView;
ThreadListView* fThreadListView; ThreadListView* fThreadListView;
@@ -167,33 +167,4 @@ private:
}; };
class TeamWindow::Listener {
public:
virtual ~Listener();
virtual void FunctionSourceCodeRequested(
FunctionInstance* function) = 0;
virtual void ImageDebugInfoRequested(Image* image) = 0;
virtual void StackFrameValueRequested(::Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path) = 0;
// called with team locked
virtual void ThreadActionRequested(thread_id threadID,
uint32 action) = 0;
virtual void SetBreakpointRequested(target_addr_t address,
bool enabled) = 0;
virtual void SetBreakpointEnabledRequested(
UserBreakpoint* breakpoint,
bool enabled) = 0;
virtual void ClearBreakpointRequested(
target_addr_t address) = 0;
virtual void ClearBreakpointRequested(
UserBreakpoint* breakpoint) = 0;
// TODO: Consolidate those!
virtual bool TeamWindowQuitRequested() = 0;
};
#endif // TEAM_WINDOW_H #endif // TEAM_WINDOW_H