* 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 "GraphicalUserInterface.h"
#include "MessageCodes.h"
#include "SettingsManager.h"
#include "TeamDebugger.h"
@@ -261,7 +262,15 @@ printf("There's already a debugger for team: %ld\n", team);
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) {
// TODO: Notify the user!
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) elf ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui util ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
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) model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
@@ -94,11 +96,17 @@ Application Debugger :
LocatableFile.cpp
SourceFile.cpp
# gui/model
# user_interface
UserInterface.cpp
# user_interface/gui
GraphicalUserInterface.cpp
# user_interface/gui/model
VariablesViewState.cpp
VariablesViewStateHistory.cpp
# gui/team_window
# user_interface/gui/team_window
BreakpointListView.cpp
BreakpointsView.cpp
ImageFunctionsView.cpp
@@ -110,7 +118,7 @@ Application Debugger :
ThreadListView.cpp
VariablesView.cpp
# gui/util
# user_interface/gui/util
TargetAddressTableColumn.cpp
# ids
@@ -185,4 +193,4 @@ Application Debugger :
HaikuSubInclude arch x86 disasm ;
HaikuSubInclude demangler ;
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 <Alert.h>
#include <Message.h>
#include <AutoLocker.h>
@@ -124,7 +123,8 @@ struct TeamDebugger::ImageHandlerHashDefinition {
// #pragma mark - TeamDebugger
TeamDebugger::TeamDebugger(Listener* listener, SettingsManager* settingsManager)
TeamDebugger::TeamDebugger(Listener* listener, UserInterface* userInterface,
SettingsManager* settingsManager)
:
BLooper("team debugger"),
fListener(listener),
@@ -137,10 +137,11 @@ TeamDebugger::TeamDebugger(Listener* listener, SettingsManager* settingsManager)
fWorker(NULL),
fBreakpointManager(NULL),
fDebugEventListener(-1),
fTeamWindow(NULL),
fUserInterface(userInterface),
fTerminating(false),
fKillTeamOnQuit(false)
{
fUserInterface->AcquireReference();
}
@@ -164,13 +165,9 @@ TeamDebugger::~TeamDebugger()
if (fDebugEventListener >= 0)
wait_for_thread(fDebugEventListener, NULL);
// 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();
}
// terminate UI
fUserInterface->Terminate();
fUserInterface->ReleaseReference();
ThreadHandler* threadHandler = fThreadHandlers.Clear(true);
while (threadHandler != NULL) {
@@ -356,16 +353,14 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
if (looperThread < 0)
return looperThread;
// create the team window
try {
fTeamWindow = TeamWindow::Create(fTeam, this);
} catch (...) {
// TODO: Notify the user!
ERROR("Error: Failed to create team window!\n");
return B_NO_MEMORY;
// init the UI
error = fUserInterface->Init(fTeam, this);
if (error != B_OK) {
ERROR("Error: Failed to init the UI: %s\n", strerror(error));
return error;
}
fTeamWindow->Show();
fUserInterface->Show();
// if requested, stop the given thread
if (threadID >= 0) {
@@ -643,7 +638,7 @@ TeamDebugger::ClearBreakpointRequested(UserBreakpoint* breakpoint)
bool
TeamDebugger::TeamWindowQuitRequested()
TeamDebugger::UserInterfaceQuitRequested()
{
AutoLocker< ::Team> locker(fTeam);
BString name(fTeam->Name());
@@ -662,10 +657,10 @@ TeamDebugger::TeamWindowQuitRequested()
BString resumeLabel("Resume ");
resumeLabel << name;
BAlert* alert = new BAlert("Quit Debugger", message.String(),
killLabel.String(), "Cancel", resumeLabel.String());
int32 choice = fUserInterface->SynchronouslyAskUser("Quit Debugger",
message, killLabel, "Cancel", resumeLabel);
switch (alert->Go()) {
switch (choice) {
case 0:
fKillTeamOnQuit = true;
break;
@@ -1291,15 +1286,8 @@ TeamDebugger::_NotifyUser(const char* title, const char* text,...)
vsnprintf(buffer, sizeof(buffer), text, args);
va_end(args);
// show the alert
BAlert* alert = new(std::nothrow) BAlert(title, buffer, "OK",
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.
// notify the user
fUserInterface->NotifyUser(title, buffer, USER_NOTIFICATION_WARNING);
}
+6 -5
View File
@@ -13,8 +13,8 @@
#include "DebugEvent.h"
#include "Team.h"
#include "TeamWindow.h"
#include "ThreadHandler.h"
#include "UserInterface.h"
#include "Worker.h"
@@ -24,13 +24,14 @@ class SettingsManager;
class TeamDebugInfo;
class TeamDebugger : public BLooper, private TeamWindow::Listener,
class TeamDebugger : public BLooper, private UserInterfaceListener,
private JobListener, private Team::Listener {
public:
class Listener;
public:
TeamDebugger(Listener* listener,
UserInterface* userInterface,
SettingsManager* settingsManager);
~TeamDebugger();
@@ -42,7 +43,7 @@ public:
virtual void MessageReceived(BMessage* message);
private:
// TeamWindow::Listener
// UserInterfaceListener
virtual void FunctionSourceCodeRequested(
FunctionInstance* function);
virtual void ImageDebugInfoRequested(Image* image);
@@ -59,7 +60,7 @@ private:
virtual void ClearBreakpointRequested(target_addr_t address);
virtual void ClearBreakpointRequested(
UserBreakpoint* breakpoint);
virtual bool TeamWindowQuitRequested();
virtual bool UserInterfaceQuitRequested();
// JobListener
virtual void JobDone(Job* job);
@@ -133,7 +134,7 @@ private:
Worker* fWorker;
BreakpointManager* fBreakpointManager;
thread_id fDebugEventListener;
TeamWindow* fTeamWindow;
UserInterface* fUserInterface;
volatile bool fTerminating;
bool fKillTeamOnQuit;
};
@@ -0,0 +1,23 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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, ingo_weinhold@gmx.de.
* 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, ingo_weinhold@gmx.de.
* 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, ingo_weinhold@gmx.de.
* 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 "Tracing.h"
#include "TypeComponentPath.h"
#include "UserInterface.h"
#include "Variable.h"
@@ -45,7 +46,7 @@ enum {
// #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,
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
@@ -107,7 +108,7 @@ TeamWindow::~TeamWindow()
/*static*/ TeamWindow*
TeamWindow::Create(::Team* team, Listener* listener)
TeamWindow::Create(::Team* team, UserInterfaceListener* listener)
{
TeamWindow* self = new TeamWindow(team, listener);
@@ -265,7 +266,7 @@ TeamWindow::MessageReceived(BMessage* message)
bool
TeamWindow::QuitRequested()
{
return fListener->TeamWindowQuitRequested();
return fListener->UserInterfaceQuitRequested();
}
@@ -968,11 +969,3 @@ TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint)
fSourceView->UserBreakpointChanged(breakpoint);
fBreakpointsView->UserBreakpointChanged(breakpoint);
}
// #pragma mark - Listener
TeamWindow::Listener::~Listener()
{
}
@@ -29,6 +29,7 @@ class RegistersView;
class SourceCode;
class StackFrame;
class UserBreakpoint;
class UserInterfaceListener;
class VariablesView;
@@ -38,13 +39,12 @@ class TeamWindow : public BWindow, ThreadListView::Listener,
SourceView::Listener, VariablesView::Listener, Team::Listener,
Function::Listener, StackFrame::Listener {
public:
class Listener;
public:
TeamWindow(::Team* team, Listener* listener);
TeamWindow(::Team* team,
UserInterfaceListener* listener);
~TeamWindow();
static TeamWindow* Create(::Team* team, Listener* listener);
static TeamWindow* Create(::Team* team,
UserInterfaceListener* listener);
// throws
virtual void DispatchMessage(BMessage* message,
@@ -148,7 +148,7 @@ private:
FunctionInstance* fActiveFunction;
SourceCode* fActiveSourceCode;
ActiveSourceObject fActiveSourceObject;
Listener* fListener;
UserInterfaceListener* fListener;
BTabView* fTabView;
BTabView* fLocalsTabView;
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