mykedge app android,MainFrame.cpp

//

// Copyright 2005 The Android Open Source Project

//

// Main window, menu bar, and associated goodies.

//

// For compilers that support precompilation, include "wx/wx.h".

#include "wx/wxprec.h"

// Otherwise, include all standard headers

#ifndef WX_PRECOMP

# include "wx/wx.h"

#endif

#include "wx/button.h"

#include "wx/help.h"

#include "wx/filedlg.h"

#include "wx/slider.h"

#include "wx/textctrl.h"

#include "MainFrame.h"

#include "MyApp.h"

#include "Resource.h"

#include "PhoneCollection.h"

#include "PhoneData.h"

#include "PhoneWindow.h"

#include "DeviceWindow.h"

#include "UserEventMessage.h"

#include "PrefsDialog.h"

#include "SimRuntime.h"

static wxString kStatusNotRunning = wxT("Idle");

static wxString kStatusRunning = wxT("Run");

static wxString kDeviceMenuString = wxT("&Device");

static const wxString gStdJavaApps[] = {

wxT(""),

wxT("com.android.testharness.TestList"),

wxT("com.android.apps.contacts.ContactsList"),

wxT("mikeapp")

};

BEGIN_EVENT_TABLE(MainFrame::MainFrame, wxFrame)

EVT_CLOSE(MainFrame::OnClose)

EVT_TIMER(kHalfSecondTimerId, MainFrame::OnTimer)

//EVT_IDLE(MainFrame::OnIdle)

EVT_ACTIVATE(MainFrame::OnActivate)

EVT_ACTIVATE_APP(MainFrame::OnActivate)

EVT_COMBOBOX(IDC_MODE_SELECT, MainFrame::OnComboBox)

EVT_COMBOBOX(IDC_JAVA_VM, MainFrame::OnComboBox)

EVT_CHECKBOX(IDC_USE_GDB, MainFrame::OnCheckBox)

EVT_CHECKBOX(IDC_USE_VALGRIND, MainFrame::OnCheckBox)

EVT_CHECKBOX(IDC_CHECK_JNI, MainFrame::OnCheckBox)

EVT_CHECKBOX(IDC_OVERLAY_ONION_SKIN, MainFrame::OnCheckBox)

EVT_TEXT(IDC_JAVA_APP_NAME, MainFrame::OnText)

EVT_TEXT_ENTER(IDC_ONION_SKIN_FILE_NAME, MainFrame::OnTextEnter)

EVT_BUTTON(IDC_ONION_SKIN_BUTTON, MainFrame::OnButton)

EVT_COMMAND_SCROLL(IDC_ONION_SKIN_ALPHA_VAL, MainFrame::OnSliderChange)

EVT_MENU(IDM_FILE_PREFERENCES, MainFrame::OnFilePreferences)

EVT_MENU(IDM_FILE_EXIT, MainFrame::OnFileExit)

EVT_MENU(IDM_RUNTIME_START, MainFrame::OnSimStart)

EVT_UPDATE_UI(IDM_RUNTIME_START, MainFrame::OnUpdateSimStart)

EVT_MENU(IDM_RUNTIME_STOP, MainFrame::OnSimStop)

EVT_UPDATE_UI(IDM_RUNTIME_STOP, MainFrame::OnUpdateSimStop)

EVT_MENU(IDM_RUNTIME_RESTART, MainFrame::OnSimRestart)

EVT_UPDATE_UI(IDM_RUNTIME_RESTART, MainFrame::OnUpdateSimRestart)

EVT_MENU(IDM_RUNTIME_KILL, MainFrame::OnSimKill)

EVT_UPDATE_UI(IDM_RUNTIME_KILL, MainFrame::OnUpdateSimKill)

EVT_MENU_RANGE(IDM_DEVICE_SEL0, IDM_DEVICE_SELN,

MainFrame::OnDeviceSelected)

EVT_MENU(IDM_DEVICE_RESCAN, MainFrame::OnDeviceRescan)

EVT_UPDATE_UI(IDM_DEBUG_SHOW_LOG, MainFrame::OnUpdateDebugShowLog)

EVT_MENU(IDM_DEBUG_SHOW_LOG, MainFrame::OnDebugShowLog)

EVT_MENU(IDM_HELP_CONTENTS, MainFrame::OnHelpContents)

EVT_MENU(IDM_HELP_ABOUT, MainFrame::OnHelpAbout)

EVT_USER_EVENT(MainFrame::OnUserEvent)

END_EVENT_TABLE()

/*

* Main window constructor.

*

* Creates menus and status bar.

*/

MainFrame::MainFrame(const wxString& title, const wxPoint& pos,

const wxSize& size, long style)

: wxFrame((wxFrame *)NULL, -1, title, pos, size, style),

mSimRunning(false),

mRestartRequested(false),

mpPhoneWindow(NULL),

mPhoneWindowPosn(wxDefaultPosition),

mTimer(this, kHalfSecondTimerId)

{

mSimAssetPath = ((MyApp*)wxTheApp)->GetSimAssetPath();

mSimAssetPath += wxT("/simulator/default/default");

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

int val;

val = mPhoneWindowPosn.x;

pPrefs->GetInt("window-device-x", &val);

mPhoneWindowPosn.x = val;

val = mPhoneWindowPosn.y;

pPrefs->GetInt("window-device-y", &val);

mPhoneWindowPosn.y = val;

/*

* Create main menu.

*/

ConstructMenu();

/*

* Create the status bar.

*/

int widths[2] = { -1, 50 };

CreateStatusBar(2, wxFULL_REPAINT_ON_RESIZE); // no wxST_SIZEGRIP

SetStatusWidths(2, widths);

SetStatusText(wxT("Ready"));

SetStatusText(kStatusNotRunning, 1);

/*

* Create main window controls.

*/

ConstructControls();

#if 0

/*

* Use the standard window color for the main frame (which usually

* has a darker color). This has a dramatic effect under Windows.

*/

wxColour color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);

SetOwnBackgroundColour(color);

#endif

/*

* Create the log window.

*/

wxRect layout = LogWindow::GetPrefWindowRect();

mpLogWindow = new LogWindow(this);

mpLogWindow->Move(layout.GetTopLeft());

mpLogWindow->SetSize(layout.GetSize());

bool showLogWindow = true;

pPrefs->GetBool("window-log-show", &showLogWindow);

if (showLogWindow)

mpLogWindow->Show();

/*

* Set up a frequent timer. We use this to keep our "run/idle"

* display up to date. (Ideally this will go away.)

*/

mTimer.Start(400); // arg is delay in ms

/*

* Handle auto-power-on by sending ourselves an event. That way it

* gets handled after window initialization finishes.

*/

bool autoPowerOn = false;

pPrefs->GetBool("auto-power-on", &autoPowerOn);

if (autoPowerOn) {

printf("Sim: Auto power-up\n");

wxCommandEvent startEvent(wxEVT_COMMAND_MENU_SELECTED, IDM_RUNTIME_START);

this->AddPendingEvent(startEvent);

}

/*

* wxThread wants these to be on the heap -- it will call delete on the

* object when the thread exits.

*/

mExternalRuntimeThread = new ExternalRuntime();

mExternalRuntimeThread->StartThread();

mPropertyServerThread = new PropertyServer();

mPropertyServerThread->StartThread();

}

/*

* Construct the main menu. Called from the constructor.

*/

void MainFrame::ConstructMenu(void)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

/*

* Scan for available phones.

*/

PhoneCollection* pCollection = PhoneCollection::GetInstance();

pCollection->ScanForPhones(mSimAssetPath.ToAscii());

/*

* Create the "File" menu.

*/

wxMenu* menuFile = new wxMenu;

menuFile->Append(IDM_FILE_PREFERENCES, wxT("&Preferences..."),

wxT("Edit simulator preferences"));

menuFile->AppendSeparator();

menuFile->Append(IDM_FILE_EXIT, wxT("E&xit\tCtrl-Q"),

wxT("Stop simulator and exit"));

/*

* Create the "Runtime" menu.

*/

wxMenu* menuRuntime = new wxMenu;

menuRuntime->Append(IDM_RUNTIME_START, wxT("&Power On\tCtrl-G"),

wxT("Start the device"));

// menuRuntime->Append(IDM_RUNTIME_STOP, wxT("Power &Off"),

// wxT("Stop the device"));

menuRuntime->AppendSeparator();

// menuRuntime->Append(IDM_RUNTIME_RESTART, wxT("&Restart"),

// wxT("Restart the device"));

menuRuntime->Append(IDM_RUNTIME_KILL, wxT("&Kill\tCtrl-K"),

wxT("Kill the runtime processes"));

/*

* Create "Device" menu.

*/

wxString defaultDevice = wxT("Sooner");

pPrefs->GetString("default-device", /*ref*/ defaultDevice);

wxMenu* menuDevice = CreateDeviceMenu(defaultDevice.ToAscii());

/*

* Create "Debug" menu.

*/

wxMenu* menuDebug = new wxMenu;

menuDebug->AppendCheckItem(IDM_DEBUG_SHOW_LOG, wxT("View &Log Output"),

wxT("View log output window"));

/*

* Create the "Help" menu.

*/

wxMenu* menuHelp = new wxMenu;

menuHelp->Append(IDM_HELP_CONTENTS, wxT("&Contents...\tF1"),

wxT("Simulator help"));

menuHelp->AppendSeparator();

menuHelp->Append(IDM_HELP_ABOUT, wxT("&About..."),

wxT("See the fabulous 'about' box"));

/*

* Create the menu bar.

*/

wxMenuBar *menuBar = new wxMenuBar;

menuBar->Append(menuFile, wxT("&File"));

menuBar->Append(menuDevice, kDeviceMenuString);

menuBar->Append(menuRuntime, wxT("&Runtime"));

menuBar->Append(menuDebug, wxT("&Debug"));

menuBar->Append(menuHelp, wxT("&Help"));

SetMenuBar(menuBar);

}

/*

* Construct the "device" menu from our phone collection.

*/

wxMenu* MainFrame::CreateDeviceMenu(const char* defaultItemName)

{

wxMenu* menuDevice = new wxMenu;

PhoneCollection* pCollection = PhoneCollection::GetInstance();

int defaultModel = 0;

for (int i = 0; i < pCollection->GetPhoneCount(); i++) {

PhoneData* pPhoneData = pCollection->GetPhoneData(i);

assert(pPhoneData != NULL);

menuDevice->AppendRadioItem(IDM_DEVICE_SEL0 + i,

wxString::FromAscii(pPhoneData->GetTitle()));

// use this one as default if the string matches

if (strcasecmp(pPhoneData->GetName(), defaultItemName) == 0)

defaultModel = i;

}

menuDevice->Check(IDM_DEVICE_SEL0 + defaultModel, true);

menuDevice->AppendSeparator();

menuDevice->Append(IDM_DEVICE_RESCAN, wxT("Re-scan"));

return menuDevice;

}

/*

* Create some controls in the main window.

*

* The main frame doesn't use the normal background color that you find

* in dialog windows, so we create a "panel" and put all the controls

* on that.

*/

void MainFrame::ConstructControls(void)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

wxPanel* base = new wxPanel(this, wxID_ANY);

wxBoxSizer* masterSizer = new wxBoxSizer(wxVERTICAL);

wxBoxSizer* tmpSizer;

wxStaticBoxSizer* displayOptSizer;

wxStaticBoxSizer* runtimeOptSizer;

wxStaticBoxSizer* onionSkinOptSizer;

wxComboBox* pModeSelection;

wxCheckBox* pUseGDB;

wxCheckBox* pUseValgrind;

wxCheckBox* pCheckJni;

wxCheckBox* pOverlayOnionSkin;

displayOptSizer = new wxStaticBoxSizer(wxHORIZONTAL, base,

wxT("Configuration"));

runtimeOptSizer = new wxStaticBoxSizer(wxVERTICAL, base,

wxT("Runtime Options"));

onionSkinOptSizer = new wxStaticBoxSizer(wxVERTICAL, base,

wxT("Onion Skin Options"));

/*

* Set up the configuration sizer (nee "display options").

*/

tmpSizer = new wxBoxSizer(wxHORIZONTAL);

displayOptSizer->Add(tmpSizer);

tmpSizer->Add(

new wxStaticText(base, wxID_ANY, wxT("Device mode:"),

wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT), 0, wxALIGN_CENTER_VERTICAL);

pModeSelection = new wxComboBox(base, IDC_MODE_SELECT, wxT(""),

wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);

tmpSizer->AddSpacer(kInterSpacing);

tmpSizer->Add(pModeSelection);

displayOptSizer->AddSpacer(kInterSpacing);

/*

* Configure the runtime options sizer.

*/

wxComboBox* pJavaAppName;

tmpSizer = new wxBoxSizer(wxHORIZONTAL);

pUseGDB = new wxCheckBox(base, IDC_USE_GDB, wxT("Use &debugger"));

tmpSizer->Add(pUseGDB);

tmpSizer->AddSpacer(kInterSpacing);

pUseValgrind = new wxCheckBox(base, IDC_USE_VALGRIND, wxT("Use &valgrind"));

tmpSizer->Add(pUseValgrind);

tmpSizer->AddSpacer(kInterSpacing);

pCheckJni = new wxCheckBox(base, IDC_CHECK_JNI, wxT("Check &JNI"));

tmpSizer->Add(pCheckJni);

pJavaAppName = new wxComboBox(base, IDC_JAVA_APP_NAME, wxT(""),

wxDefaultPosition, wxSize(320, -1), NELEM(gStdJavaApps), gStdJavaApps,

wxCB_DROPDOWN);

wxBoxSizer* javaAppSizer = new wxBoxSizer(wxHORIZONTAL);

javaAppSizer->Add(

new wxStaticText(base, wxID_ANY,

wxT("Java app:"),

wxDefaultPosition, wxDefaultSize,

wxALIGN_LEFT),

0, wxALIGN_CENTER_VERTICAL);

javaAppSizer->AddSpacer(kInterSpacing);

javaAppSizer->Add(pJavaAppName);

runtimeOptSizer->Add(tmpSizer);

runtimeOptSizer->AddSpacer(kInterSpacing);

runtimeOptSizer->Add(javaAppSizer);

runtimeOptSizer->AddSpacer(kInterSpacing);

wxString tmpStr;

SetCheckFromPref(pUseGDB, "debug", false);

SetCheckFromPref(pUseValgrind, "valgrind", false);

SetCheckFromPref(pCheckJni, "check-jni", false);

if (pPrefs->GetString("java-app-name", /*ref*/ tmpStr))

pJavaAppName->SetValue(tmpStr);

/*

* Configure the onion skin options sizer.

*/

wxTextCtrl* pOnionSkinFileNameText;

wxButton* pOnionSkinFileButton;

wxSlider* pOnionSkinAlphaSlider;

tmpSizer = new wxBoxSizer(wxHORIZONTAL);

pOverlayOnionSkin = new wxCheckBox(base,

IDC_OVERLAY_ONION_SKIN, wxT("Overlay &onion skin"));

tmpSizer->Add(pOverlayOnionSkin);

pOnionSkinFileNameText = new wxTextCtrl(base,

IDC_ONION_SKIN_FILE_NAME, wxT(""),

wxDefaultPosition, wxSize(250, -1),

wxTE_PROCESS_ENTER);

pOnionSkinFileButton = new wxButton(base, IDC_ONION_SKIN_BUTTON,

wxT("Choose"));

wxBoxSizer* onionSkinFileNameSizer = new wxBoxSizer(wxHORIZONTAL);

onionSkinFileNameSizer->Add(

new wxStaticText(base, wxID_ANY,

wxT("Filename:"),

wxDefaultPosition, wxDefaultSize,

wxALIGN_LEFT),

0, wxALIGN_CENTER_VERTICAL);

onionSkinFileNameSizer->AddSpacer(kInterSpacing);

onionSkinFileNameSizer->Add(pOnionSkinFileNameText);

onionSkinFileNameSizer->Add(pOnionSkinFileButton);

wxBoxSizer * onionSkinAlphaSizer = new wxBoxSizer(wxHORIZONTAL);

int initialAlphaVal = 127;

pPrefs->GetInt("onion-skin-alpha-value", &initialAlphaVal);

pOnionSkinAlphaSlider = new wxSlider(base, IDC_ONION_SKIN_ALPHA_VAL,

initialAlphaVal, 0, 255, wxDefaultPosition, wxSize(150, 20));

onionSkinAlphaSizer->Add(

new wxStaticText(base, wxID_ANY,

wxT("Transparency:"),

wxDefaultPosition, wxDefaultSize,

wxALIGN_LEFT),

0, wxALIGN_CENTER_VERTICAL);

onionSkinAlphaSizer->AddSpacer(kInterSpacing);

onionSkinAlphaSizer->Add(pOnionSkinAlphaSlider, 1, wxCENTRE | wxALL, 5);

onionSkinOptSizer->Add(tmpSizer);

onionSkinOptSizer->AddSpacer(kInterSpacing);

onionSkinOptSizer->Add(onionSkinFileNameSizer);

onionSkinOptSizer->Add(onionSkinAlphaSizer);

wxString tmpStr2;

SetCheckFromPref(pOverlayOnionSkin, "overlay-onion-skin", false);

if (pPrefs->GetString("onion-skin-file-name", /*ref*/ tmpStr2))

pOnionSkinFileNameText->SetValue(tmpStr2);

/*

* Add the various components to the master sizer.

*/

masterSizer->Add(displayOptSizer);

masterSizer->AddSpacer(kInterSpacing * 2);

masterSizer->Add(runtimeOptSizer);

masterSizer->AddSpacer(kInterSpacing * 2);

masterSizer->Add(onionSkinOptSizer);

//masterSizer->AddSpacer(kInterSpacing);

/*

* I don't see a way to guarantee that the window is wide enough to

* show the entire menu bar, so just throw some pixels at it.

*/

wxBoxSizer* minWidthSizer = new wxBoxSizer(wxVERTICAL);

minWidthSizer->Add(300, kEdgeSpacing); // forces minimum width

minWidthSizer->Add(masterSizer);

minWidthSizer->AddSpacer(kInterSpacing * 2);

/* move us a few pixels in from the left */

wxBoxSizer* indentSizer = new wxBoxSizer(wxHORIZONTAL);

indentSizer->AddSpacer(kEdgeSpacing);

indentSizer->Add(minWidthSizer);

indentSizer->AddSpacer(kEdgeSpacing);

base->SetSizer(indentSizer);

indentSizer->Fit(this);

indentSizer->SetSizeHints(this);

}

/*

* Set the value of a checkbox based on a value from the config file.

*/

void MainFrame::SetCheckFromPref(wxCheckBox* pControl, const char* prefStr,

bool defaultVal)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

bool val = defaultVal;

pPrefs->GetBool(prefStr, &val);

pControl->SetValue(val);

}

/*

* Destructor.

*/

MainFrame::~MainFrame(void)

{

PhoneCollection::DestroyInstance();

delete mExternalRuntimeThread;

delete mPropertyServerThread;

// don't touch mpModeSelection -- child of window

}

/*

* File->Quit or click on close box.

*

* If we want an "are you sure you want to quit" box, add it here.

*/

void MainFrame::OnClose(wxCloseEvent& event)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

/*

if (event.CanVeto())

printf("Closing (can veto)\n");

else

printf("Closing (mandatory)\n");

*/

/*

* Generally speaking, Close() is not guaranteed to close the window.

* However, we want to use it here because (a) our windows are

* guaranteed to close, and (b) it provides our windows an opportunity

* to tell others that they are about to vanish.

*/

if (mpPhoneWindow != NULL)

mpPhoneWindow->Close(true);

/* save position of main window */

wxPoint pos = GetPosition();

pPrefs->SetInt("window-main-x", pos.x);

pPrefs->SetInt("window-main-y", pos.y);

/* save default device selection */

int idx = GetSelectedDeviceIndex();

if (idx >= 0) {

PhoneCollection* pCollection = PhoneCollection::GetInstance();

PhoneData* pPhoneData = pCollection->GetPhoneData(idx);

pPrefs->SetString("default-device", pPhoneData->GetName());

}

if (mpLogWindow != NULL)

mpLogWindow->Close(true);

Destroy();

}

/*

* File->Preferences

*/

void MainFrame::OnFilePreferences(wxCommandEvent& WXUNUSED(event))

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

PrefsDialog dialog(this);

int result;

result = dialog.ShowModal();

if (result == wxID_OK) {

/*

* The dialog handles writing changes to Preferences, so all we

* need to deal with here are changes that have an immediate

* impact on us. (which is currently nothing)

*/

}

}

/*

* File->Exit

*/

void MainFrame::OnFileExit(wxCommandEvent& WXUNUSED(event))

{

Close(FALSE); // false means "allow veto"

}

/*

* Decide whether Simulator->Start should be enabled.

*/

void MainFrame::OnUpdateSimStart(wxUpdateUIEvent& event)

{

if (IsRuntimeRunning())

event.Enable(FALSE);

else

event.Enable(TRUE);

}

/*

* Simulator->Start

*/

void MainFrame::OnSimStart(wxCommandEvent& WXUNUSED(event))

{

// keyboard equivalents can still get here even if menu item disabled

if (IsRuntimeRunning())

return;

int id = GetSelectedDeviceIndex();

if (id < 0) {

fprintf(stderr, "Sim: could not identify currently selected device\n");

return;

}

#if 0

static int foo = 0;

foo++;

if (foo == 2) {

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

pPrefs->SetBool("debug", true);

}

#endif

SetupPhoneUI(id, NULL);

if (mpPhoneWindow != NULL)

mpPhoneWindow->GetDeviceManager()->StartRuntime();

}

/*

* Decide whether Simulator->Stop should be enabled.

*/

void MainFrame::OnUpdateSimStop(wxUpdateUIEvent& event)

{

if (IsRuntimeRunning())

event.Enable(TRUE);

else

event.Enable(FALSE);

}

/*

* Simulator->Stop

*/

void MainFrame::OnSimStop(wxCommandEvent& WXUNUSED(event))

{

if (!IsRuntimeRunning())

return;

assert(mpPhoneWindow != NULL);

mpPhoneWindow->GetDeviceManager()->StopRuntime();

}

/*

* Decide whether Simulator->Restart should be enabled.

*/

void MainFrame::OnUpdateSimRestart(wxUpdateUIEvent& event)

{

if (IsRuntimeRunning())

event.Enable(TRUE);

else

event.Enable(FALSE);

}

/*

* Simulator->Restart - stop then start the device runtime.

*/

void MainFrame::OnSimRestart(wxCommandEvent& WXUNUSED(event))

{

if (!IsRuntimeRunning())

return;

printf("Restart requested\n");

mpPhoneWindow->GetDeviceManager()->StopRuntime();

mRestartRequested = true;

}

/*

* Decide whether Simulator->Kill should be enabled.

*/

void MainFrame::OnUpdateSimKill(wxUpdateUIEvent& event)

{

if (IsRuntimeKillable())

event.Enable(TRUE);

else

event.Enable(FALSE);

}

/*

* Simulator->Kill

*/

void MainFrame::OnSimKill(wxCommandEvent& WXUNUSED(event))

{

if (!IsRuntimeKillable())

return;

assert(mpPhoneWindow != NULL);

mpPhoneWindow->GetDeviceManager()->KillRuntime();

}

/*

* Device->[select]

*/

void MainFrame::OnDeviceSelected(wxCommandEvent& event)

{

wxBusyCursor busyc;

int id = event.GetId() - IDM_DEVICE_SEL0;

SetupPhoneUI(id, NULL);

}

/*

* Device->Rescan

*/

void MainFrame::OnDeviceRescan(wxCommandEvent& event)

{

wxBusyCursor busyc;

wxMenuBar* pMenuBar;

PhoneCollection* pCollection;

wxMenu* pOldMenu;

wxMenu* pNewMenu;

const char* curDevName = NULL;

int idx;

/* figure out the current device name */

pCollection = PhoneCollection::GetInstance();

idx = GetSelectedDeviceIndex();

if (idx >= 0) {

PhoneData* pPhoneData;

pPhoneData = pCollection->GetPhoneData(idx);

curDevName = pPhoneData->GetName();

printf("--- device name is '%s'\n", (const char*) curDevName);

}

/* reconstruct device menu with new data */

#ifdef BEFORE_ASSET

pCollection->ScanForPhones(mSimAssetPath);

#else

pCollection->ScanForPhones(NULL);

#endif

pMenuBar = GetMenuBar();

idx = pMenuBar->FindMenu(kDeviceMenuString);

if (idx == wxNOT_FOUND) {

fprintf(stderr, "Sim: couldn't find %s menu\n", (const char*) kDeviceMenuString.ToAscii());

return;

}

pNewMenu = CreateDeviceMenu(curDevName);

pOldMenu = pMenuBar->Replace(idx, pNewMenu, kDeviceMenuString);

delete pOldMenu;

/* tell the PhoneWindow about it; may cause runtime to exit */

if (mpPhoneWindow != NULL)

mpPhoneWindow->DevicesRescanned();

}

/*

* Set checkbox on menu item.

*/

void MainFrame::OnUpdateDebugShowLog(wxUpdateUIEvent& event)

{

if (mpLogWindow == NULL) {

event.Enable(false);

} else {

event.Enable(true);

event.Check(mpLogWindow->IsShown());

}

}

/*

* Debug->ShowLog toggle.

*/

void MainFrame::OnDebugShowLog(wxCommandEvent& WXUNUSED(event))

{

mpLogWindow->Show(!mpLogWindow->IsShown());

}

/*

* Help->Contents

*/

void MainFrame::OnHelpContents(wxCommandEvent& WXUNUSED(event))

{

((MyApp*)wxTheApp)->GetHelpController()->DisplayContents();

}

/*

* Help->About

*/

void MainFrame::OnHelpAbout(wxCommandEvent& WXUNUSED(event))

{

wxMessageBox(wxT("Android Simulator v0.1\n"

"Copyright 2006 The Android Open Source Project"),

wxT("About..."), wxOK | wxICON_INFORMATION, this);

}

/*

* Sent from phonewindow or when activated

*/

void MainFrame::OnActivate(wxActivateEvent& event)

{

#if 0

if (event.GetActive())

{

if (mpPhoneWindow != NULL &&

mpPhoneWindow->GetDeviceManager()->RefreshRuntime())

{

wxString msg;

int sel;

msg = wxT("Newer runtime executable found. Would you like to reload the device?");

sel = wxMessageBox(msg, wxT("Android Safety Patrol"),

wxYES | wxNO | wxICON_QUESTION, mpPhoneWindow);

//printf("BUTTON was %d (yes=%d)\n", sel, wxYES);

if (sel == wxYES)

{

mpPhoneWindow->GetDeviceManager()->StopRuntime();

mpPhoneWindow->Close();

mpPhoneWindow = NULL;

mRestartRequested = true;

}

else

{

mpPhoneWindow->GetDeviceManager()->UserCancelledRefresh();

}

}

}

#endif

// let wxWidgets do whatever it needs to do

event.Skip();

}

/*

* Device mode selection box.

*/

void MainFrame::OnComboBox(wxCommandEvent& event)

{

const char* pref;

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

if (IDC_MODE_SELECT == event.GetId())

{

int id = GetSelectedDeviceIndex();

if (id < 0)

return;

//printf("--- mode selected: '%s'\n", (const char*) event.GetString().ToAscii());

/*

* Call the phone window's setup function. Don't call our SetupPhoneUI

* function from here -- updating the combo box from a combo box callback

* could cause problems.

*/

if (mpPhoneWindow != NULL) {

mpPhoneWindow->SetCurrentMode(event.GetString());

mpPhoneWindow->Setup(id);

}

} else if (event.GetId() == IDC_JAVA_VM) {

wxComboBox* pBox = (wxComboBox*) FindWindow(IDC_JAVA_VM);

pPrefs->SetString("java-vm", pBox->GetValue().ToAscii());

}

}

/*

* One of our option checkboxes has been changed.

*

* We update the prefs database so that the settings are retained when

* the simulator is next used.

*/

void MainFrame::OnCheckBox(wxCommandEvent& event)

{

const char* pref;

switch (event.GetId()) {

case IDC_USE_GDB: pref = "debug"; break;

case IDC_USE_VALGRIND: pref = "valgrind"; break;

case IDC_CHECK_JNI: pref = "check-jni"; break;

case IDC_OVERLAY_ONION_SKIN: pref = "overlay-onion-skin"; break;

default:

printf("Sim: unrecognized checkbox %d in OnCheckBox\n", event.GetId());

return;

}

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

pPrefs->SetBool(pref, (bool) event.GetInt());

//printf("--- set pref '%s' to %d\n", pref, (bool) event.GetInt());

if (event.GetId() == IDC_OVERLAY_ONION_SKIN) {

BroadcastOnionSkinUpdate();

}

if (event.GetId() == IDC_CHECK_JNI) {

const char* val = "0";

if ((bool) event.GetInt())

val = "1";

mPropertyServerThread->SetProperty(PropertyServer::kPropCheckJni, val);

}

}

void MainFrame::BroadcastOnionSkinUpdate() {

if (mpPhoneWindow != NULL) {

// broadcast a user event indicating an onion skin update

UserEvent uev(0, (void*) -1);

mpPhoneWindow->GetDeviceManager()->BroadcastEvent(uev);

}

}

/*

* A text control on the main page is being updated.

*

* The current implementation updates the preferences database on every

* change, which is a bit silly but is easy to do.

*/

void MainFrame::OnText(wxCommandEvent& event)

{

const char* pref;

switch (event.GetId()) {

case IDC_JAVA_APP_NAME: pref = "java-app-name"; break;

default:

printf("Sim: unrecognized textctrl %d in OnText\n", event.GetId());

return;

}

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

// event.GetString() does not work on Mac -- always blank

//pPrefs->SetString(pref, event.GetString());

assert(event.GetId() == IDC_JAVA_APP_NAME); // fix if we add more

wxComboBox* pBox;

pBox = (wxComboBox*) FindWindow(IDC_JAVA_APP_NAME);

pPrefs->SetString(pref, pBox->GetValue().ToAscii());

//printf("--- set pref '%s' to '%s'\n", pref,(const char*)pBox->GetValue());

}

/*

* A user pressed enter in a text control on the main page.

*

* The current implementation updates the preferences database on every

* change, which is a bit silly but is easy to do.

*/

void MainFrame::OnTextEnter(wxCommandEvent& event)

{

const char* pref;

switch (event.GetId()) {

case IDC_ONION_SKIN_FILE_NAME:

pref = "onion-skin-file-name";

break;

default:

printf("Sim: unrecognized textctrl %d in OnTextEnter\n", event.GetId());

return;

}

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

assert(event.GetId() == IDC_ONION_SKIN_FILE_NAME); // fix if we add more

wxTextCtrl* pTextCtrl;

pTextCtrl = (wxTextCtrl*) FindWindow(IDC_ONION_SKIN_FILE_NAME);

wxString onionSkinFileNameWxString = pTextCtrl->GetValue();

char* onionSkinFileName = "";

if (onionSkinFileNameWxString.Len() > 0) {

onionSkinFileName = android::strdupNew(onionSkinFileNameWxString.ToAscii());

}

pPrefs->SetString(pref, onionSkinFileName);

BroadcastOnionSkinUpdate();

}

/*

* A user pressed a button on the main page

*

*/

void MainFrame::OnButton(wxCommandEvent& event)

{

wxWindow* base;

wxFileDialog* pOnionSkinFileChooser;

int retVal;

switch (event.GetId()) {

case IDC_ONION_SKIN_BUTTON:

base = FindWindow(IDC_ONION_SKIN_BUTTON)->GetParent();

pOnionSkinFileChooser = new wxFileDialog(base,

wxT("Choose the onion skin image file."),

wxT(""), wxT(""), wxT("*.*"),

wxOPEN | wxFILE_MUST_EXIST);

retVal = pOnionSkinFileChooser->ShowModal();

if (retVal == pOnionSkinFileChooser->GetAffirmativeId()) {

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

wxString fileNameWxString = pOnionSkinFileChooser->GetPath();

const char* fileName = android::strdupNew(fileNameWxString.ToAscii());

wxTextCtrl* fileTextCtrl = (wxTextCtrl*) FindWindow(IDC_ONION_SKIN_FILE_NAME);

fileTextCtrl->SetValue(fileNameWxString);

pPrefs->SetString("onion-skin-file-name", fileName);

BroadcastOnionSkinUpdate();

}

break;

default:

printf("Sim: unrecognized button %d in OnButton\n", event.GetId());

return;

}

}

/*

* The user moved a slider on the main page

*/

void MainFrame::OnSliderChange(wxScrollEvent& event)

{

wxSlider* pSlider;

Preferences* pPrefs;

switch (event.GetId()) {

case IDC_ONION_SKIN_ALPHA_VAL:

pSlider = (wxSlider*) FindWindow(IDC_ONION_SKIN_ALPHA_VAL);

pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

pPrefs->SetInt("onion-skin-alpha-value", pSlider->GetValue());

BroadcastOnionSkinUpdate();

break;

default:

printf("Sim: unrecognized scroller or slider %d in OnSliderChange\n", event.GetId());

return;

}

}

#if 0

/*

* Idle processing. Under wxWidgets this only called once after UI

* activity unless you call event.RequestMore().

*/

void MainFrame::OnIdle(wxIdleEvent& event)

{

event.Skip(); // let base class handler do stuff

}

#endif

/*

* Handle the timer.

*

* This is being called in the main thread, so multithreading with the

* rest of MainFrame isn't a concern here.

*/

void MainFrame::OnTimer(wxTimerEvent& event)

{

bool status;

/*

* Check to see if the runtime died without telling us. This can only

* happen if we forcibly kill our thread. We shouldn't really be

* doing that anymore, but keep this in for now just in case.

*/

status = IsRuntimeRunning();

if (mSimRunning != status) {

if (!status) {

printf("Sim: fixed mSimRunning=%d actual=%d\n",

mSimRunning, status);

mSimRunning = status;

if (!status)

HandleRuntimeStop();

} else {

/*

* This was happening when we were shutting down but the

* device management thread hadn't completely gone away. The

* simple IsRunning test passes, so we get a false positive.

* Ignore it.

*/

}

}

if (gWantToKill) {

if (IsRuntimeRunning()) {

printf("Sim: handling kill request\n");

mpPhoneWindow->GetDeviceManager()->KillRuntime();

}

gWantToKill = false;

/* see if Ctrl-C should kill us too */

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

bool die = false;

pPrefs->GetBool("trap-sigint-suicide", &die);

if (die) {

printf("Sim: goodbye cruel world!\n");

exit(0);

}

}

}

/*

* Determine whether or not the simulator is running.

*/

bool MainFrame::IsRuntimeRunning(void)

{

bool result;

if (mpPhoneWindow == NULL)

result = false;

else if (!mpPhoneWindow->IsReady())

result = false;

else

result = mpPhoneWindow->GetDeviceManager()->IsRunning();

return result;

}

/*

* Determine whether or not the runtime can be killed.

*/

bool MainFrame::IsRuntimeKillable(void)

{

bool result;

result = IsRuntimeRunning();

if (result)

result = mpPhoneWindow->GetDeviceManager()->IsKillable();

return result;

}

/*

* Determine whether two devices are sufficiently compatible.

*/

bool MainFrame::CompatibleDevices(PhoneData* pData1, PhoneData* pData2)

{

int displayCount;

displayCount = pData1->GetNumDisplays();

if (pData2->GetNumDisplays() != displayCount)

return false;

for (int i = 0; i < displayCount; i++) {

PhoneDisplay* pDisplay1 = pData1->GetPhoneDisplay(i);

PhoneDisplay* pDisplay2 = pData2->GetPhoneDisplay(i);

if (!PhoneDisplay::IsCompatible(pDisplay1, pDisplay2))

return false;

}

return true;

}

/*

* (Re-)arrange the UI for the currently selected phone model.

*

* If the simulator is running, and the set of displays for the current

* device are incompatible with the new device, we need to restart the

* runtime. We need to ask for permission first though.

*/

void MainFrame::SetupPhoneUI(int idx, const char* defaultMode)

{

PhoneCollection* pCollection;

PhoneData* pPhoneData;

wxString* choices = NULL;

int numChoices = 0;

int numKeyboards = 0;

bool haveDefaultMode = false;

wxCharBuffer currentMode;

int i;

pCollection = PhoneCollection::GetInstance();

pPhoneData = pCollection->GetPhoneData(idx);

if (pPhoneData == NULL) {

fprintf(stderr, "ERROR: device index %d not valid\n", idx);

goto bail;

}

/*

* We have a window up. If the displays aren't compatible, we'll

* need to recreate it.

*/

if (mpPhoneWindow != NULL) {

PhoneData* pCurData = mpPhoneWindow->GetPhoneData();

if (!CompatibleDevices(pCurData, pPhoneData)) {

/*

* We need to trash the window. This will also kill the

* runtime. If it's running, ask permission.

*/

if (IsRuntimeRunning()) {

wxString msg;

int sel;

msg = wxT("Switching to the new device requires restarting the");

msg += wxT(" runtime. Continue?");

sel = wxMessageBox(msg, wxT("Android Safety Patrol"),

wxOK | wxCANCEL | wxICON_QUESTION, this);

printf("BUTTON was %d (ok=%d)\n", sel, wxOK);

if (sel == wxCANCEL)

goto bail;

/* shut it down (politely), ask for an eventual restart */

mpPhoneWindow->GetDeviceManager()->StopRuntime();

mpPhoneWindow->Close();

mpPhoneWindow = NULL;

mRestartRequested = true;

goto bail;

} else {

/* not running, just trash the window and continue */

mpPhoneWindow->Close();

mpPhoneWindow = NULL;

}

}

}

/*

* Figure out the set of available modes.

*/

numChoices = pPhoneData->GetNumModes();

if (numChoices > 0) {

choices = new wxString[numChoices];

for (i = 0; i < numChoices; i++) {

PhoneMode* pPhoneMode;

pPhoneMode = pPhoneData->GetPhoneMode(i);

choices[i] = wxString::FromAscii(pPhoneMode->GetName());

if (defaultMode != NULL &&

strcmp(defaultMode, pPhoneMode->GetName()) == 0)

{

haveDefaultMode = true;

}

}

}

if (choices == NULL) {

/* had a failure earlier; configure UI with default stuff */

choices = new wxString[1];

choices[0] = wxT("(none)");

}

if (!haveDefaultMode) {

/*

* Default mode wasn't found. If we specify it as the default

* in the wxComboBox create call it shows up in the combo box

* under Linux, even if it doesn't exist in the list. So, we

* make sure that it doesn't get used if we can't find it.

*/

if (defaultMode != NULL) {

printf("Sim: HEY: default mode '%s' not found in list\n",

defaultMode);

}

currentMode = choices[0].ToAscii();

} else {

currentMode = defaultMode;

}

/*

* Create the window if necessary.

*/

if (mpPhoneWindow == NULL) {

// create, setup, and then show window

mpPhoneWindow = new PhoneWindow(this, mPhoneWindowPosn);

mpPhoneWindow->SetCurrentMode((const char*)currentMode);

if (!mpPhoneWindow->Setup(idx)) {

delete mpPhoneWindow;

mpPhoneWindow = NULL;

}

if (mpPhoneWindow != NULL) {

mpPhoneWindow->Show();

//mpPhoneWindow->CheckPlacement();

}

} else {

// just set up for new device

mpPhoneWindow->SetCurrentMode((const char*)currentMode);

if (!mpPhoneWindow->Setup(idx)) {

// it's in an uncertain state, blow it away

delete mpPhoneWindow;

mpPhoneWindow = NULL;

}

}

/*

* Reconfigure mode selection box.

*/

wxComboBox* pModeSelection;

pModeSelection = (wxComboBox*)FindWindow(IDC_MODE_SELECT);

pModeSelection->Clear();

for (i = 0; i < numChoices; i++)

pModeSelection->Append(choices[i]);

pModeSelection->SetSelection(0);

pModeSelection->Enable(numChoices > 1);

/*

* configure qwerty keyboard attribute

*/

numKeyboards = pPhoneData->GetNumKeyboards();

if (numKeyboards > 0) {

// only use the first keyboard for now

PhoneKeyboard* pPhoneKeyboard;

pPhoneKeyboard = pPhoneData->GetPhoneKeyboard(0);

if (pPhoneKeyboard->getQwerty()) {

printf("Sim: set 'qwerty' env\n");

setenv("qwerty", "true", true);

}

}

bail:

delete[] choices;

}

/*

* Figure out which device is currently selected.

*

* The easiest way to do this is just run down the list of possible IDs

* and stop when something claims to be checked.

*

* Returns -1 if it can't find a checked item (which can happen if no

* device layouts were found).

*/

int MainFrame::GetSelectedDeviceIndex(void)

{

wxMenuBar* pMenuBar;

wxMenu* pMenu;

int idx;

pMenuBar = GetMenuBar();

idx = pMenuBar->FindMenu(kDeviceMenuString);

if (idx == wxNOT_FOUND) {

fprintf(stderr, "Sim: couldn't find %s menu\n", (const char*) kDeviceMenuString.ToAscii());

return -1;

}

pMenu = pMenuBar->GetMenu(idx);

//printf("Menu.MenuItemCount = %d\n", pMenu->GetMenuItemCount());

for (int j = pMenu->GetMenuItemCount() -1; j >= 0; j--) {

wxMenuItem* pItem;

pItem = pMenu->FindItemByPosition(j);

//printf("ITEM %d: %s\n", j, (const char*) pItem->GetLabel());

if (pItem->IsChecked()) {

printf("Sim: selected device is '%s'\n",

(const char*) pItem->GetLabel().ToAscii());

return j;

}

}

return -1;

}

/*

* Receive a status message from the runtime thread.

*/

void MainFrame::OnUserEvent(UserEvent& event)

{

UserEventMessage* pUem;

pUem = (UserEventMessage*) event.GetData();

assert(pUem != NULL);

switch (pUem->GetType()) {

case UserEventMessage::kRuntimeStarted:

printf("Sim: runtime thread started!\n");

HandleRuntimeStart();

break;

case UserEventMessage::kRuntimeStopped:

printf("Sim: runtime thread stopped!\n");

HandleRuntimeStop();

break;

case UserEventMessage::kErrorMessage:

{

wxString msg = pUem->GetString();

wxMessageBox(msg, wxT("Android Runtime Error"),

wxOK | wxICON_WARNING, this);

}

break;

case UserEventMessage::kLogMessage:

mpLogWindow->AddLogMessage(pUem->GetLogMessage());

break;

case UserEventMessage::kExternalRuntime:

HandleExternalRuntime(pUem->GetReader(), pUem->GetWriter());

break;

default:

printf("Sim: MESSAGE: unknown UserEventMessage rcvd (type=%d)\n",

pUem->GetType());

break;

}

delete pUem;

}

/*

* The device management thread is up, so the runtime should be fully

* running shortly.

*/

void MainFrame::HandleRuntimeStart(void)

{

mSimRunning = true;

SetStatusText(kStatusRunning, 1);

}

/*

* The device management thread is exiting, so the runtime must be dead.

*/

void MainFrame::HandleRuntimeStop(void)

{

mSimRunning = false;

SetStatusText(kStatusNotRunning, 1);

if (mRestartRequested) {

printf("Sim: restarting runtime\n");

mRestartRequested = false;

SetupPhoneUI(GetSelectedDeviceIndex(), NULL);

if (mpPhoneWindow != NULL)

mpPhoneWindow->GetDeviceManager()->StartRuntime();

}

}

/*

* Handle a connection from an external runtime.

*/

void MainFrame::HandleExternalRuntime(android::Pipe* reader,

android::Pipe* writer)

{

android::MessageStream msgStream;

android::Message msg;

if (IsRuntimeRunning()) {

/*

* Tell the new guy to go away.

*/

if (!msgStream.init(reader, writer, true)) {

fprintf(stderr, "Sim: WARNING: unable to talk to remote runtime\n");

goto bail;

}

printf("Sim: telling external runtime to go away\n");

msg.setCommand(android::Simulator::kCommandGoAway, 0);

msgStream.send(&msg);

} else {

printf("Sim: new external runtime wants to talk to us\n");

/*

* Launch the pieces necessary to talk to this guy.

*/

int id = GetSelectedDeviceIndex();

if (id < 0) {

fprintf(stderr,

"Sim: could not identify currently selected device\n");

goto bail;

}

/* kill existing window, so it pops up and reclaims focus */

if (mpPhoneWindow != NULL) {

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

bool okay;

if (pPrefs->GetBool("refocus-on-restart", &okay) && okay) {

printf("Sim: inducing phone window refocus\n");

mpPhoneWindow->Close(TRUE); // no veto

mpPhoneWindow = NULL;

}

}

SetupPhoneUI(id, NULL);

if (mpPhoneWindow != NULL) {

mpPhoneWindow->GetDeviceManager()->StartRuntime(reader, writer);

} else {

fprintf(stderr, "Sim: ERROR: unable to get runtime going\n");

goto bail;

}

// we don't own these anymore

reader = writer = NULL;

}

bail:

delete reader;

delete writer;

}

/*

* The phone window is about to destroy itself. Get rid of our pointer

* to it, and record its last position so we can create the new one in

* the same place.

*/

void MainFrame::PhoneWindowClosing(int x, int y)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

mpPhoneWindow = NULL;

mPhoneWindowPosn.x = x;

mPhoneWindowPosn.y = y;

pPrefs->SetInt("window-device-x", x);

pPrefs->SetInt("window-device-y", y);

}

C++程序

|

1463行

|

41.9 KB

//

// Copyright 2005 The Android Open Source Project

//

// Main window, menu bar, and associated goodies.

//

// For compilers that support precompilation, include "wx/wx.h".

#include "wx/wxprec.h"

// Otherwise, include all standard headers

#ifndef WX_PRECOMP

# include "wx/wx.h"

#endif

#include "wx/button.h"

#include "wx/help.h"

#include "wx/filedlg.h"

#include "wx/slider.h"

#include "wx/textctrl.h"

#include "MainFrame.h"

#include "MyApp.h"

#include "Resource.h"

#include "PhoneCollection.h"

#include "PhoneData.h"

#include "PhoneWindow.h"

#include "DeviceWindow.h"

#include "UserEventMessage.h"

#include "PrefsDialog.h"

#include "SimRuntime.h"

static wxString kStatusNotRunning = wxT("Idle");

static wxString kStatusRunning = wxT("Run");

static wxString kDeviceMenuString = wxT("&Device");

static const wxString gStdJavaApps[] = {

wxT(""),

wxT("com.android.testharness.TestList"),

wxT("com.android.apps.contacts.ContactsList"),

wxT("mikeapp")

};

BEGIN_EVENT_TABLE(MainFrame::MainFrame, wxFrame)

EVT_CLOSE(MainFrame::OnClose)

EVT_TIMER(kHalfSecondTimerId, MainFrame::OnTimer)

//EVT_IDLE(MainFrame::OnIdle)

EVT_ACTIVATE(MainFrame::OnActivate)

EVT_ACTIVATE_APP(MainFrame::OnActivate)

EVT_COMBOBOX(IDC_MODE_SELECT, MainFrame::OnComboBox)

EVT_COMBOBOX(IDC_JAVA_VM, MainFrame::OnComboBox)

EVT_CHECKBOX(IDC_USE_GDB, MainFrame::OnCheckBox)

EVT_CHECKBOX(IDC_USE_VALGRIND, MainFrame::OnCheckBox)

EVT_CHECKBOX(IDC_CHECK_JNI, MainFrame::OnCheckBox)

EVT_CHECKBOX(IDC_OVERLAY_ONION_SKIN, MainFrame::OnCheckBox)

EVT_TEXT(IDC_JAVA_APP_NAME, MainFrame::OnText)

EVT_TEXT_ENTER(IDC_ONION_SKIN_FILE_NAME, MainFrame::OnTextEnter)

EVT_BUTTON(IDC_ONION_SKIN_BUTTON, MainFrame::OnButton)

EVT_COMMAND_SCROLL(IDC_ONION_SKIN_ALPHA_VAL, MainFrame::OnSliderChange)

EVT_MENU(IDM_FILE_PREFERENCES, MainFrame::OnFilePreferences)

EVT_MENU(IDM_FILE_EXIT, MainFrame::OnFileExit)

EVT_MENU(IDM_RUNTIME_START, MainFrame::OnSimStart)

EVT_UPDATE_UI(IDM_RUNTIME_START, MainFrame::OnUpdateSimStart)

EVT_MENU(IDM_RUNTIME_STOP, MainFrame::OnSimStop)

EVT_UPDATE_UI(IDM_RUNTIME_STOP, MainFrame::OnUpdateSimStop)

EVT_MENU(IDM_RUNTIME_RESTART, MainFrame::OnSimRestart)

EVT_UPDATE_UI(IDM_RUNTIME_RESTART, MainFrame::OnUpdateSimRestart)

EVT_MENU(IDM_RUNTIME_KILL, MainFrame::OnSimKill)

EVT_UPDATE_UI(IDM_RUNTIME_KILL, MainFrame::OnUpdateSimKill)

EVT_MENU_RANGE(IDM_DEVICE_SEL0, IDM_DEVICE_SELN,

MainFrame::OnDeviceSelected)

EVT_MENU(IDM_DEVICE_RESCAN, MainFrame::OnDeviceRescan)

EVT_UPDATE_UI(IDM_DEBUG_SHOW_LOG, MainFrame::OnUpdateDebugShowLog)

EVT_MENU(IDM_DEBUG_SHOW_LOG, MainFrame::OnDebugShowLog)

EVT_MENU(IDM_HELP_CONTENTS, MainFrame::OnHelpContents)

EVT_MENU(IDM_HELP_ABOUT, MainFrame::OnHelpAbout)

EVT_USER_EVENT(MainFrame::OnUserEvent)

END_EVENT_TABLE()

/*

* Main window constructor.

*

* Creates menus and status bar.

*/

MainFrame::MainFrame(const wxString& title, const wxPoint& pos,

const wxSize& size, long style)

: wxFrame((wxFrame *)NULL, -1, title, pos, size, style),

mSimRunning(false),

mRestartRequested(false),

mpPhoneWindow(NULL),

mPhoneWindowPosn(wxDefaultPosition),

mTimer(this, kHalfSecondTimerId)

{

mSimAssetPath = ((MyApp*)wxTheApp)->GetSimAssetPath();

mSimAssetPath += wxT("/simulator/default/default");

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

int val;

val = mPhoneWindowPosn.x;

pPrefs->GetInt("window-device-x", &val);

mPhoneWindowPosn.x = val;

val = mPhoneWindowPosn.y;

pPrefs->GetInt("window-device-y", &val);

mPhoneWindowPosn.y = val;

/*

* Create main menu.

*/

ConstructMenu();

/*

* Create the status bar.

*/

int widths[2] = { -1, 50 };

CreateStatusBar(2, wxFULL_REPAINT_ON_RESIZE); // no wxST_SIZEGRIP

SetStatusWidths(2, widths);

SetStatusText(wxT("Ready"));

SetStatusText(kStatusNotRunning, 1);

/*

* Create main window controls.

*/

ConstructControls();

#if 0

/*

* Use the standard window color for the main frame (which usually

* has a darker color). This has a dramatic effect under Windows.

*/

wxColour color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);

SetOwnBackgroundColour(color);

#endif

/*

* Create the log window.

*/

wxRect layout = LogWindow::GetPrefWindowRect();

mpLogWindow = new LogWindow(this);

mpLogWindow->Move(layout.GetTopLeft());

mpLogWindow->SetSize(layout.GetSize());

bool showLogWindow = true;

pPrefs->GetBool("window-log-show", &showLogWindow);

if (showLogWindow)

mpLogWindow->Show();

/*

* Set up a frequent timer. We use this to keep our "run/idle"

* display up to date. (Ideally this will go away.)

*/

mTimer.Start(400); // arg is delay in ms

/*

* Handle auto-power-on by sending ourselves an event. That way it

* gets handled after window initialization finishes.

*/

bool autoPowerOn = false;

pPrefs->GetBool("auto-power-on", &autoPowerOn);

if (autoPowerOn) {

printf("Sim: Auto power-up\n");

wxCommandEvent startEvent(wxEVT_COMMAND_MENU_SELECTED, IDM_RUNTIME_START);

this->AddPendingEvent(startEvent);

}

/*

* wxThread wants these to be on the heap -- it will call delete on the

* object when the thread exits.

*/

mExternalRuntimeThread = new ExternalRuntime();

mExternalRuntimeThread->StartThread();

mPropertyServerThread = new PropertyServer();

mPropertyServerThread->StartThread();

}

/*

* Construct the main menu. Called from the constructor.

*/

void MainFrame::ConstructMenu(void)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

/*

* Scan for available phones.

*/

PhoneCollection* pCollection = PhoneCollection::GetInstance();

pCollection->ScanForPhones(mSimAssetPath.ToAscii());

/*

* Create the "File" menu.

*/

wxMenu* menuFile = new wxMenu;

menuFile->Append(IDM_FILE_PREFERENCES, wxT("&Preferences..."),

wxT("Edit simulator preferences"));

menuFile->AppendSeparator();

menuFile->Append(IDM_FILE_EXIT, wxT("E&xit\tCtrl-Q"),

wxT("Stop simulator and exit"));

/*

* Create the "Runtime" menu.

*/

wxMenu* menuRuntime = new wxMenu;

menuRuntime->Append(IDM_RUNTIME_START, wxT("&Power On\tCtrl-G"),

wxT("Start the device"));

// menuRuntime->Append(IDM_RUNTIME_STOP, wxT("Power &Off"),

// wxT("Stop the device"));

menuRuntime->AppendSeparator();

// menuRuntime->Append(IDM_RUNTIME_RESTART, wxT("&Restart"),

// wxT("Restart the device"));

menuRuntime->Append(IDM_RUNTIME_KILL, wxT("&Kill\tCtrl-K"),

wxT("Kill the runtime processes"));

/*

* Create "Device" menu.

*/

wxString defaultDevice = wxT("Sooner");

pPrefs->GetString("default-device", /*ref*/ defaultDevice);

wxMenu* menuDevice = CreateDeviceMenu(defaultDevice.ToAscii());

/*

* Create "Debug" menu.

*/

wxMenu* menuDebug = new wxMenu;

menuDebug->AppendCheckItem(IDM_DEBUG_SHOW_LOG, wxT("View &Log Output"),

wxT("View log output window"));

/*

* Create the "Help" menu.

*/

wxMenu* menuHelp = new wxMenu;

menuHelp->Append(IDM_HELP_CONTENTS, wxT("&Contents...\tF1"),

wxT("Simulator help"));

menuHelp->AppendSeparator();

menuHelp->Append(IDM_HELP_ABOUT, wxT("&About..."),

wxT("See the fabulous 'about' box"));

/*

* Create the menu bar.

*/

wxMenuBar *menuBar = new wxMenuBar;

menuBar->Append(menuFile, wxT("&File"));

menuBar->Append(menuDevice, kDeviceMenuString);

menuBar->Append(menuRuntime, wxT("&Runtime"));

menuBar->Append(menuDebug, wxT("&Debug"));

menuBar->Append(menuHelp, wxT("&Help"));

SetMenuBar(menuBar);

}

/*

* Construct the "device" menu from our phone collection.

*/

wxMenu* MainFrame::CreateDeviceMenu(const char* defaultItemName)

{

wxMenu* menuDevice = new wxMenu;

PhoneCollection* pCollection = PhoneCollection::GetInstance();

int defaultModel = 0;

for (int i = 0; i < pCollection->GetPhoneCount(); i++) {

PhoneData* pPhoneData = pCollection->GetPhoneData(i);

assert(pPhoneData != NULL);

menuDevice->AppendRadioItem(IDM_DEVICE_SEL0 + i,

wxString::FromAscii(pPhoneData->GetTitle()));

// use this one as default if the string matches

if (strcasecmp(pPhoneData->GetName(), defaultItemName) == 0)

defaultModel = i;

}

menuDevice->Check(IDM_DEVICE_SEL0 + defaultModel, true);

menuDevice->AppendSeparator();

menuDevice->Append(IDM_DEVICE_RESCAN, wxT("Re-scan"));

return menuDevice;

}

/*

* Create some controls in the main window.

*

* The main frame doesn't use the normal background color that you find

* in dialog windows, so we create a "panel" and put all the controls

* on that.

*/

void MainFrame::ConstructControls(void)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

wxPanel* base = new wxPanel(this, wxID_ANY);

wxBoxSizer* masterSizer = new wxBoxSizer(wxVERTICAL);

wxBoxSizer* tmpSizer;

wxStaticBoxSizer* displayOptSizer;

wxStaticBoxSizer* runtimeOptSizer;

wxStaticBoxSizer* onionSkinOptSizer;

wxComboBox* pModeSelection;

wxCheckBox* pUseGDB;

wxCheckBox* pUseValgrind;

wxCheckBox* pCheckJni;

wxCheckBox* pOverlayOnionSkin;

displayOptSizer = new wxStaticBoxSizer(wxHORIZONTAL, base,

wxT("Configuration"));

runtimeOptSizer = new wxStaticBoxSizer(wxVERTICAL, base,

wxT("Runtime Options"));

onionSkinOptSizer = new wxStaticBoxSizer(wxVERTICAL, base,

wxT("Onion Skin Options"));

/*

* Set up the configuration sizer (nee "display options").

*/

tmpSizer = new wxBoxSizer(wxHORIZONTAL);

displayOptSizer->Add(tmpSizer);

tmpSizer->Add(

new wxStaticText(base, wxID_ANY, wxT("Device mode:"),

wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT), 0, wxALIGN_CENTER_VERTICAL);

pModeSelection = new wxComboBox(base, IDC_MODE_SELECT, wxT(""),

wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);

tmpSizer->AddSpacer(kInterSpacing);

tmpSizer->Add(pModeSelection);

displayOptSizer->AddSpacer(kInterSpacing);

/*

* Configure the runtime options sizer.

*/

wxComboBox* pJavaAppName;

tmpSizer = new wxBoxSizer(wxHORIZONTAL);

pUseGDB = new wxCheckBox(base, IDC_USE_GDB, wxT("Use &debugger"));

tmpSizer->Add(pUseGDB);

tmpSizer->AddSpacer(kInterSpacing);

pUseValgrind = new wxCheckBox(base, IDC_USE_VALGRIND, wxT("Use &valgrind"));

tmpSizer->Add(pUseValgrind);

tmpSizer->AddSpacer(kInterSpacing);

pCheckJni = new wxCheckBox(base, IDC_CHECK_JNI, wxT("Check &JNI"));

tmpSizer->Add(pCheckJni);

pJavaAppName = new wxComboBox(base, IDC_JAVA_APP_NAME, wxT(""),

wxDefaultPosition, wxSize(320, -1), NELEM(gStdJavaApps), gStdJavaApps,

wxCB_DROPDOWN);

wxBoxSizer* javaAppSizer = new wxBoxSizer(wxHORIZONTAL);

javaAppSizer->Add(

new wxStaticText(base, wxID_ANY,

wxT("Java app:"),

wxDefaultPosition, wxDefaultSize,

wxALIGN_LEFT),

0, wxALIGN_CENTER_VERTICAL);

javaAppSizer->AddSpacer(kInterSpacing);

javaAppSizer->Add(pJavaAppName);

runtimeOptSizer->Add(tmpSizer);

runtimeOptSizer->AddSpacer(kInterSpacing);

runtimeOptSizer->Add(javaAppSizer);

runtimeOptSizer->AddSpacer(kInterSpacing);

wxString tmpStr;

SetCheckFromPref(pUseGDB, "debug", false);

SetCheckFromPref(pUseValgrind, "valgrind", false);

SetCheckFromPref(pCheckJni, "check-jni", false);

if (pPrefs->GetString("java-app-name", /*ref*/ tmpStr))

pJavaAppName->SetValue(tmpStr);

/*

* Configure the onion skin options sizer.

*/

wxTextCtrl* pOnionSkinFileNameText;

wxButton* pOnionSkinFileButton;

wxSlider* pOnionSkinAlphaSlider;

tmpSizer = new wxBoxSizer(wxHORIZONTAL);

pOverlayOnionSkin = new wxCheckBox(base,

IDC_OVERLAY_ONION_SKIN, wxT("Overlay &onion skin"));

tmpSizer->Add(pOverlayOnionSkin);

pOnionSkinFileNameText = new wxTextCtrl(base,

IDC_ONION_SKIN_FILE_NAME, wxT(""),

wxDefaultPosition, wxSize(250, -1),

wxTE_PROCESS_ENTER);

pOnionSkinFileButton = new wxButton(base, IDC_ONION_SKIN_BUTTON,

wxT("Choose"));

wxBoxSizer* onionSkinFileNameSizer = new wxBoxSizer(wxHORIZONTAL);

onionSkinFileNameSizer->Add(

new wxStaticText(base, wxID_ANY,

wxT("Filename:"),

wxDefaultPosition, wxDefaultSize,

wxALIGN_LEFT),

0, wxALIGN_CENTER_VERTICAL);

onionSkinFileNameSizer->AddSpacer(kInterSpacing);

onionSkinFileNameSizer->Add(pOnionSkinFileNameText);

onionSkinFileNameSizer->Add(pOnionSkinFileButton);

wxBoxSizer * onionSkinAlphaSizer = new wxBoxSizer(wxHORIZONTAL);

int initialAlphaVal = 127;

pPrefs->GetInt("onion-skin-alpha-value", &initialAlphaVal);

pOnionSkinAlphaSlider = new wxSlider(base, IDC_ONION_SKIN_ALPHA_VAL,

initialAlphaVal, 0, 255, wxDefaultPosition, wxSize(150, 20));

onionSkinAlphaSizer->Add(

new wxStaticText(base, wxID_ANY,

wxT("Transparency:"),

wxDefaultPosition, wxDefaultSize,

wxALIGN_LEFT),

0, wxALIGN_CENTER_VERTICAL);

onionSkinAlphaSizer->AddSpacer(kInterSpacing);

onionSkinAlphaSizer->Add(pOnionSkinAlphaSlider, 1, wxCENTRE | wxALL, 5);

onionSkinOptSizer->Add(tmpSizer);

onionSkinOptSizer->AddSpacer(kInterSpacing);

onionSkinOptSizer->Add(onionSkinFileNameSizer);

onionSkinOptSizer->Add(onionSkinAlphaSizer);

wxString tmpStr2;

SetCheckFromPref(pOverlayOnionSkin, "overlay-onion-skin", false);

if (pPrefs->GetString("onion-skin-file-name", /*ref*/ tmpStr2))

pOnionSkinFileNameText->SetValue(tmpStr2);

/*

* Add the various components to the master sizer.

*/

masterSizer->Add(displayOptSizer);

masterSizer->AddSpacer(kInterSpacing * 2);

masterSizer->Add(runtimeOptSizer);

masterSizer->AddSpacer(kInterSpacing * 2);

masterSizer->Add(onionSkinOptSizer);

//masterSizer->AddSpacer(kInterSpacing);

/*

* I don't see a way to guarantee that the window is wide enough to

* show the entire menu bar, so just throw some pixels at it.

*/

wxBoxSizer* minWidthSizer = new wxBoxSizer(wxVERTICAL);

minWidthSizer->Add(300, kEdgeSpacing); // forces minimum width

minWidthSizer->Add(masterSizer);

minWidthSizer->AddSpacer(kInterSpacing * 2);

/* move us a few pixels in from the left */

wxBoxSizer* indentSizer = new wxBoxSizer(wxHORIZONTAL);

indentSizer->AddSpacer(kEdgeSpacing);

indentSizer->Add(minWidthSizer);

indentSizer->AddSpacer(kEdgeSpacing);

base->SetSizer(indentSizer);

indentSizer->Fit(this);

indentSizer->SetSizeHints(this);

}

/*

* Set the value of a checkbox based on a value from the config file.

*/

void MainFrame::SetCheckFromPref(wxCheckBox* pControl, const char* prefStr,

bool defaultVal)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

bool val = defaultVal;

pPrefs->GetBool(prefStr, &val);

pControl->SetValue(val);

}

/*

* Destructor.

*/

MainFrame::~MainFrame(void)

{

PhoneCollection::DestroyInstance();

delete mExternalRuntimeThread;

delete mPropertyServerThread;

// don't touch mpModeSelection -- child of window

}

/*

* File->Quit or click on close box.

*

* If we want an "are you sure you want to quit" box, add it here.

*/

void MainFrame::OnClose(wxCloseEvent& event)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

/*

if (event.CanVeto())

printf("Closing (can veto)\n");

else

printf("Closing (mandatory)\n");

*/

/*

* Generally speaking, Close() is not guaranteed to close the window.

* However, we want to use it here because (a) our windows are

* guaranteed to close, and (b) it provides our windows an opportunity

* to tell others that they are about to vanish.

*/

if (mpPhoneWindow != NULL)

mpPhoneWindow->Close(true);

/* save position of main window */

wxPoint pos = GetPosition();

pPrefs->SetInt("window-main-x", pos.x);

pPrefs->SetInt("window-main-y", pos.y);

/* save default device selection */

int idx = GetSelectedDeviceIndex();

if (idx >= 0) {

PhoneCollection* pCollection = PhoneCollection::GetInstance();

PhoneData* pPhoneData = pCollection->GetPhoneData(idx);

pPrefs->SetString("default-device", pPhoneData->GetName());

}

if (mpLogWindow != NULL)

mpLogWindow->Close(true);

Destroy();

}

/*

* File->Preferences

*/

void MainFrame::OnFilePreferences(wxCommandEvent& WXUNUSED(event))

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

PrefsDialog dialog(this);

int result;

result = dialog.ShowModal();

if (result == wxID_OK) {

/*

* The dialog handles writing changes to Preferences, so all we

* need to deal with here are changes that have an immediate

* impact on us. (which is currently nothing)

*/

}

}

/*

* File->Exit

*/

void MainFrame::OnFileExit(wxCommandEvent& WXUNUSED(event))

{

Close(FALSE); // false means "allow veto"

}

/*

* Decide whether Simulator->Start should be enabled.

*/

void MainFrame::OnUpdateSimStart(wxUpdateUIEvent& event)

{

if (IsRuntimeRunning())

event.Enable(FALSE);

else

event.Enable(TRUE);

}

/*

* Simulator->Start

*/

void MainFrame::OnSimStart(wxCommandEvent& WXUNUSED(event))

{

// keyboard equivalents can still get here even if menu item disabled

if (IsRuntimeRunning())

return;

int id = GetSelectedDeviceIndex();

if (id < 0) {

fprintf(stderr, "Sim: could not identify currently selected device\n");

return;

}

#if 0

static int foo = 0;

foo++;

if (foo == 2) {

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

pPrefs->SetBool("debug", true);

}

#endif

SetupPhoneUI(id, NULL);

if (mpPhoneWindow != NULL)

mpPhoneWindow->GetDeviceManager()->StartRuntime();

}

/*

* Decide whether Simulator->Stop should be enabled.

*/

void MainFrame::OnUpdateSimStop(wxUpdateUIEvent& event)

{

if (IsRuntimeRunning())

event.Enable(TRUE);

else

event.Enable(FALSE);

}

/*

* Simulator->Stop

*/

void MainFrame::OnSimStop(wxCommandEvent& WXUNUSED(event))

{

if (!IsRuntimeRunning())

return;

assert(mpPhoneWindow != NULL);

mpPhoneWindow->GetDeviceManager()->StopRuntime();

}

/*

* Decide whether Simulator->Restart should be enabled.

*/

void MainFrame::OnUpdateSimRestart(wxUpdateUIEvent& event)

{

if (IsRuntimeRunning())

event.Enable(TRUE);

else

event.Enable(FALSE);

}

/*

* Simulator->Restart - stop then start the device runtime.

*/

void MainFrame::OnSimRestart(wxCommandEvent& WXUNUSED(event))

{

if (!IsRuntimeRunning())

return;

printf("Restart requested\n");

mpPhoneWindow->GetDeviceManager()->StopRuntime();

mRestartRequested = true;

}

/*

* Decide whether Simulator->Kill should be enabled.

*/

void MainFrame::OnUpdateSimKill(wxUpdateUIEvent& event)

{

if (IsRuntimeKillable())

event.Enable(TRUE);

else

event.Enable(FALSE);

}

/*

* Simulator->Kill

*/

void MainFrame::OnSimKill(wxCommandEvent& WXUNUSED(event))

{

if (!IsRuntimeKillable())

return;

assert(mpPhoneWindow != NULL);

mpPhoneWindow->GetDeviceManager()->KillRuntime();

}

/*

* Device->[select]

*/

void MainFrame::OnDeviceSelected(wxCommandEvent& event)

{

wxBusyCursor busyc;

int id = event.GetId() - IDM_DEVICE_SEL0;

SetupPhoneUI(id, NULL);

}

/*

* Device->Rescan

*/

void MainFrame::OnDeviceRescan(wxCommandEvent& event)

{

wxBusyCursor busyc;

wxMenuBar* pMenuBar;

PhoneCollection* pCollection;

wxMenu* pOldMenu;

wxMenu* pNewMenu;

const char* curDevName = NULL;

int idx;

/* figure out the current device name */

pCollection = PhoneCollection::GetInstance();

idx = GetSelectedDeviceIndex();

if (idx >= 0) {

PhoneData* pPhoneData;

pPhoneData = pCollection->GetPhoneData(idx);

curDevName = pPhoneData->GetName();

printf("--- device name is '%s'\n", (const char*) curDevName);

}

/* reconstruct device menu with new data */

#ifdef BEFORE_ASSET

pCollection->ScanForPhones(mSimAssetPath);

#else

pCollection->ScanForPhones(NULL);

#endif

pMenuBar = GetMenuBar();

idx = pMenuBar->FindMenu(kDeviceMenuString);

if (idx == wxNOT_FOUND) {

fprintf(stderr, "Sim: couldn't find %s menu\n", (const char*) kDeviceMenuString.ToAscii());

return;

}

pNewMenu = CreateDeviceMenu(curDevName);

pOldMenu = pMenuBar->Replace(idx, pNewMenu, kDeviceMenuString);

delete pOldMenu;

/* tell the PhoneWindow about it; may cause runtime to exit */

if (mpPhoneWindow != NULL)

mpPhoneWindow->DevicesRescanned();

}

/*

* Set checkbox on menu item.

*/

void MainFrame::OnUpdateDebugShowLog(wxUpdateUIEvent& event)

{

if (mpLogWindow == NULL) {

event.Enable(false);

} else {

event.Enable(true);

event.Check(mpLogWindow->IsShown());

}

}

/*

* Debug->ShowLog toggle.

*/

void MainFrame::OnDebugShowLog(wxCommandEvent& WXUNUSED(event))

{

mpLogWindow->Show(!mpLogWindow->IsShown());

}

/*

* Help->Contents

*/

void MainFrame::OnHelpContents(wxCommandEvent& WXUNUSED(event))

{

((MyApp*)wxTheApp)->GetHelpController()->DisplayContents();

}

/*

* Help->About

*/

void MainFrame::OnHelpAbout(wxCommandEvent& WXUNUSED(event))

{

wxMessageBox(wxT("Android Simulator v0.1\n"

"Copyright 2006 The Android Open Source Project"),

wxT("About..."), wxOK | wxICON_INFORMATION, this);

}

/*

* Sent from phonewindow or when activated

*/

void MainFrame::OnActivate(wxActivateEvent& event)

{

#if 0

if (event.GetActive())

{

if (mpPhoneWindow != NULL &&

mpPhoneWindow->GetDeviceManager()->RefreshRuntime())

{

wxString msg;

int sel;

msg = wxT("Newer runtime executable found. Would you like to reload the device?");

sel = wxMessageBox(msg, wxT("Android Safety Patrol"),

wxYES | wxNO | wxICON_QUESTION, mpPhoneWindow);

//printf("BUTTON was %d (yes=%d)\n", sel, wxYES);

if (sel == wxYES)

{

mpPhoneWindow->GetDeviceManager()->StopRuntime();

mpPhoneWindow->Close();

mpPhoneWindow = NULL;

mRestartRequested = true;

}

else

{

mpPhoneWindow->GetDeviceManager()->UserCancelledRefresh();

}

}

}

#endif

// let wxWidgets do whatever it needs to do

event.Skip();

}

/*

* Device mode selection box.

*/

void MainFrame::OnComboBox(wxCommandEvent& event)

{

const char* pref;

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

if (IDC_MODE_SELECT == event.GetId())

{

int id = GetSelectedDeviceIndex();

if (id < 0)

return;

//printf("--- mode selected: '%s'\n", (const char*) event.GetString().ToAscii());

/*

* Call the phone window's setup function. Don't call our SetupPhoneUI

* function from here -- updating the combo box from a combo box callback

* could cause problems.

*/

if (mpPhoneWindow != NULL) {

mpPhoneWindow->SetCurrentMode(event.GetString());

mpPhoneWindow->Setup(id);

}

} else if (event.GetId() == IDC_JAVA_VM) {

wxComboBox* pBox = (wxComboBox*) FindWindow(IDC_JAVA_VM);

pPrefs->SetString("java-vm", pBox->GetValue().ToAscii());

}

}

/*

* One of our option checkboxes has been changed.

*

* We update the prefs database so that the settings are retained when

* the simulator is next used.

*/

void MainFrame::OnCheckBox(wxCommandEvent& event)

{

const char* pref;

switch (event.GetId()) {

case IDC_USE_GDB: pref = "debug"; break;

case IDC_USE_VALGRIND: pref = "valgrind"; break;

case IDC_CHECK_JNI: pref = "check-jni"; break;

case IDC_OVERLAY_ONION_SKIN: pref = "overlay-onion-skin"; break;

default:

printf("Sim: unrecognized checkbox %d in OnCheckBox\n", event.GetId());

return;

}

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

pPrefs->SetBool(pref, (bool) event.GetInt());

//printf("--- set pref '%s' to %d\n", pref, (bool) event.GetInt());

if (event.GetId() == IDC_OVERLAY_ONION_SKIN) {

BroadcastOnionSkinUpdate();

}

if (event.GetId() == IDC_CHECK_JNI) {

const char* val = "0";

if ((bool) event.GetInt())

val = "1";

mPropertyServerThread->SetProperty(PropertyServer::kPropCheckJni, val);

}

}

void MainFrame::BroadcastOnionSkinUpdate() {

if (mpPhoneWindow != NULL) {

// broadcast a user event indicating an onion skin update

UserEvent uev(0, (void*) -1);

mpPhoneWindow->GetDeviceManager()->BroadcastEvent(uev);

}

}

/*

* A text control on the main page is being updated.

*

* The current implementation updates the preferences database on every

* change, which is a bit silly but is easy to do.

*/

void MainFrame::OnText(wxCommandEvent& event)

{

const char* pref;

switch (event.GetId()) {

case IDC_JAVA_APP_NAME: pref = "java-app-name"; break;

default:

printf("Sim: unrecognized textctrl %d in OnText\n", event.GetId());

return;

}

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

// event.GetString() does not work on Mac -- always blank

//pPrefs->SetString(pref, event.GetString());

assert(event.GetId() == IDC_JAVA_APP_NAME); // fix if we add more

wxComboBox* pBox;

pBox = (wxComboBox*) FindWindow(IDC_JAVA_APP_NAME);

pPrefs->SetString(pref, pBox->GetValue().ToAscii());

//printf("--- set pref '%s' to '%s'\n", pref,(const char*)pBox->GetValue());

}

/*

* A user pressed enter in a text control on the main page.

*

* The current implementation updates the preferences database on every

* change, which is a bit silly but is easy to do.

*/

void MainFrame::OnTextEnter(wxCommandEvent& event)

{

const char* pref;

switch (event.GetId()) {

case IDC_ONION_SKIN_FILE_NAME:

pref = "onion-skin-file-name";

break;

default:

printf("Sim: unrecognized textctrl %d in OnTextEnter\n", event.GetId());

return;

}

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

assert(event.GetId() == IDC_ONION_SKIN_FILE_NAME); // fix if we add more

wxTextCtrl* pTextCtrl;

pTextCtrl = (wxTextCtrl*) FindWindow(IDC_ONION_SKIN_FILE_NAME);

wxString onionSkinFileNameWxString = pTextCtrl->GetValue();

char* onionSkinFileName = "";

if (onionSkinFileNameWxString.Len() > 0) {

onionSkinFileName = android::strdupNew(onionSkinFileNameWxString.ToAscii());

}

pPrefs->SetString(pref, onionSkinFileName);

BroadcastOnionSkinUpdate();

}

/*

* A user pressed a button on the main page

*

*/

void MainFrame::OnButton(wxCommandEvent& event)

{

wxWindow* base;

wxFileDialog* pOnionSkinFileChooser;

int retVal;

switch (event.GetId()) {

case IDC_ONION_SKIN_BUTTON:

base = FindWindow(IDC_ONION_SKIN_BUTTON)->GetParent();

pOnionSkinFileChooser = new wxFileDialog(base,

wxT("Choose the onion skin image file."),

wxT(""), wxT(""), wxT("*.*"),

wxOPEN | wxFILE_MUST_EXIST);

retVal = pOnionSkinFileChooser->ShowModal();

if (retVal == pOnionSkinFileChooser->GetAffirmativeId()) {

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

wxString fileNameWxString = pOnionSkinFileChooser->GetPath();

const char* fileName = android::strdupNew(fileNameWxString.ToAscii());

wxTextCtrl* fileTextCtrl = (wxTextCtrl*) FindWindow(IDC_ONION_SKIN_FILE_NAME);

fileTextCtrl->SetValue(fileNameWxString);

pPrefs->SetString("onion-skin-file-name", fileName);

BroadcastOnionSkinUpdate();

}

break;

default:

printf("Sim: unrecognized button %d in OnButton\n", event.GetId());

return;

}

}

/*

* The user moved a slider on the main page

*/

void MainFrame::OnSliderChange(wxScrollEvent& event)

{

wxSlider* pSlider;

Preferences* pPrefs;

switch (event.GetId()) {

case IDC_ONION_SKIN_ALPHA_VAL:

pSlider = (wxSlider*) FindWindow(IDC_ONION_SKIN_ALPHA_VAL);

pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

assert(pPrefs != NULL);

pPrefs->SetInt("onion-skin-alpha-value", pSlider->GetValue());

BroadcastOnionSkinUpdate();

break;

default:

printf("Sim: unrecognized scroller or slider %d in OnSliderChange\n", event.GetId());

return;

}

}

#if 0

/*

* Idle processing. Under wxWidgets this only called once after UI

* activity unless you call event.RequestMore().

*/

void MainFrame::OnIdle(wxIdleEvent& event)

{

event.Skip(); // let base class handler do stuff

}

#endif

/*

* Handle the timer.

*

* This is being called in the main thread, so multithreading with the

* rest of MainFrame isn't a concern here.

*/

void MainFrame::OnTimer(wxTimerEvent& event)

{

bool status;

/*

* Check to see if the runtime died without telling us. This can only

* happen if we forcibly kill our thread. We shouldn't really be

* doing that anymore, but keep this in for now just in case.

*/

status = IsRuntimeRunning();

if (mSimRunning != status) {

if (!status) {

printf("Sim: fixed mSimRunning=%d actual=%d\n",

mSimRunning, status);

mSimRunning = status;

if (!status)

HandleRuntimeStop();

} else {

/*

* This was happening when we were shutting down but the

* device management thread hadn't completely gone away. The

* simple IsRunning test passes, so we get a false positive.

* Ignore it.

*/

}

}

if (gWantToKill) {

if (IsRuntimeRunning()) {

printf("Sim: handling kill request\n");

mpPhoneWindow->GetDeviceManager()->KillRuntime();

}

gWantToKill = false;

/* see if Ctrl-C should kill us too */

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

bool die = false;

pPrefs->GetBool("trap-sigint-suicide", &die);

if (die) {

printf("Sim: goodbye cruel world!\n");

exit(0);

}

}

}

/*

* Determine whether or not the simulator is running.

*/

bool MainFrame::IsRuntimeRunning(void)

{

bool result;

if (mpPhoneWindow == NULL)

result = false;

else if (!mpPhoneWindow->IsReady())

result = false;

else

result = mpPhoneWindow->GetDeviceManager()->IsRunning();

return result;

}

/*

* Determine whether or not the runtime can be killed.

*/

bool MainFrame::IsRuntimeKillable(void)

{

bool result;

result = IsRuntimeRunning();

if (result)

result = mpPhoneWindow->GetDeviceManager()->IsKillable();

return result;

}

/*

* Determine whether two devices are sufficiently compatible.

*/

bool MainFrame::CompatibleDevices(PhoneData* pData1, PhoneData* pData2)

{

int displayCount;

displayCount = pData1->GetNumDisplays();

if (pData2->GetNumDisplays() != displayCount)

return false;

for (int i = 0; i < displayCount; i++) {

PhoneDisplay* pDisplay1 = pData1->GetPhoneDisplay(i);

PhoneDisplay* pDisplay2 = pData2->GetPhoneDisplay(i);

if (!PhoneDisplay::IsCompatible(pDisplay1, pDisplay2))

return false;

}

return true;

}

/*

* (Re-)arrange the UI for the currently selected phone model.

*

* If the simulator is running, and the set of displays for the current

* device are incompatible with the new device, we need to restart the

* runtime. We need to ask for permission first though.

*/

void MainFrame::SetupPhoneUI(int idx, const char* defaultMode)

{

PhoneCollection* pCollection;

PhoneData* pPhoneData;

wxString* choices = NULL;

int numChoices = 0;

int numKeyboards = 0;

bool haveDefaultMode = false;

wxCharBuffer currentMode;

int i;

pCollection = PhoneCollection::GetInstance();

pPhoneData = pCollection->GetPhoneData(idx);

if (pPhoneData == NULL) {

fprintf(stderr, "ERROR: device index %d not valid\n", idx);

goto bail;

}

/*

* We have a window up. If the displays aren't compatible, we'll

* need to recreate it.

*/

if (mpPhoneWindow != NULL) {

PhoneData* pCurData = mpPhoneWindow->GetPhoneData();

if (!CompatibleDevices(pCurData, pPhoneData)) {

/*

* We need to trash the window. This will also kill the

* runtime. If it's running, ask permission.

*/

if (IsRuntimeRunning()) {

wxString msg;

int sel;

msg = wxT("Switching to the new device requires restarting the");

msg += wxT(" runtime. Continue?");

sel = wxMessageBox(msg, wxT("Android Safety Patrol"),

wxOK | wxCANCEL | wxICON_QUESTION, this);

printf("BUTTON was %d (ok=%d)\n", sel, wxOK);

if (sel == wxCANCEL)

goto bail;

/* shut it down (politely), ask for an eventual restart */

mpPhoneWindow->GetDeviceManager()->StopRuntime();

mpPhoneWindow->Close();

mpPhoneWindow = NULL;

mRestartRequested = true;

goto bail;

} else {

/* not running, just trash the window and continue */

mpPhoneWindow->Close();

mpPhoneWindow = NULL;

}

}

}

/*

* Figure out the set of available modes.

*/

numChoices = pPhoneData->GetNumModes();

if (numChoices > 0) {

choices = new wxString[numChoices];

for (i = 0; i < numChoices; i++) {

PhoneMode* pPhoneMode;

pPhoneMode = pPhoneData->GetPhoneMode(i);

choices[i] = wxString::FromAscii(pPhoneMode->GetName());

if (defaultMode != NULL &&

strcmp(defaultMode, pPhoneMode->GetName()) == 0)

{

haveDefaultMode = true;

}

}

}

if (choices == NULL) {

/* had a failure earlier; configure UI with default stuff */

choices = new wxString[1];

choices[0] = wxT("(none)");

}

if (!haveDefaultMode) {

/*

* Default mode wasn't found. If we specify it as the default

* in the wxComboBox create call it shows up in the combo box

* under Linux, even if it doesn't exist in the list. So, we

* make sure that it doesn't get used if we can't find it.

*/

if (defaultMode != NULL) {

printf("Sim: HEY: default mode '%s' not found in list\n",

defaultMode);

}

currentMode = choices[0].ToAscii();

} else {

currentMode = defaultMode;

}

/*

* Create the window if necessary.

*/

if (mpPhoneWindow == NULL) {

// create, setup, and then show window

mpPhoneWindow = new PhoneWindow(this, mPhoneWindowPosn);

mpPhoneWindow->SetCurrentMode((const char*)currentMode);

if (!mpPhoneWindow->Setup(idx)) {

delete mpPhoneWindow;

mpPhoneWindow = NULL;

}

if (mpPhoneWindow != NULL) {

mpPhoneWindow->Show();

//mpPhoneWindow->CheckPlacement();

}

} else {

// just set up for new device

mpPhoneWindow->SetCurrentMode((const char*)currentMode);

if (!mpPhoneWindow->Setup(idx)) {

// it's in an uncertain state, blow it away

delete mpPhoneWindow;

mpPhoneWindow = NULL;

}

}

/*

* Reconfigure mode selection box.

*/

wxComboBox* pModeSelection;

pModeSelection = (wxComboBox*)FindWindow(IDC_MODE_SELECT);

pModeSelection->Clear();

for (i = 0; i < numChoices; i++)

pModeSelection->Append(choices[i]);

pModeSelection->SetSelection(0);

pModeSelection->Enable(numChoices > 1);

/*

* configure qwerty keyboard attribute

*/

numKeyboards = pPhoneData->GetNumKeyboards();

if (numKeyboards > 0) {

// only use the first keyboard for now

PhoneKeyboard* pPhoneKeyboard;

pPhoneKeyboard = pPhoneData->GetPhoneKeyboard(0);

if (pPhoneKeyboard->getQwerty()) {

printf("Sim: set 'qwerty' env\n");

setenv("qwerty", "true", true);

}

}

bail:

delete[] choices;

}

/*

* Figure out which device is currently selected.

*

* The easiest way to do this is just run down the list of possible IDs

* and stop when something claims to be checked.

*

* Returns -1 if it can't find a checked item (which can happen if no

* device layouts were found).

*/

int MainFrame::GetSelectedDeviceIndex(void)

{

wxMenuBar* pMenuBar;

wxMenu* pMenu;

int idx;

pMenuBar = GetMenuBar();

idx = pMenuBar->FindMenu(kDeviceMenuString);

if (idx == wxNOT_FOUND) {

fprintf(stderr, "Sim: couldn't find %s menu\n", (const char*) kDeviceMenuString.ToAscii());

return -1;

}

pMenu = pMenuBar->GetMenu(idx);

//printf("Menu.MenuItemCount = %d\n", pMenu->GetMenuItemCount());

for (int j = pMenu->GetMenuItemCount() -1; j >= 0; j--) {

wxMenuItem* pItem;

pItem = pMenu->FindItemByPosition(j);

//printf("ITEM %d: %s\n", j, (const char*) pItem->GetLabel());

if (pItem->IsChecked()) {

printf("Sim: selected device is '%s'\n",

(const char*) pItem->GetLabel().ToAscii());

return j;

}

}

return -1;

}

/*

* Receive a status message from the runtime thread.

*/

void MainFrame::OnUserEvent(UserEvent& event)

{

UserEventMessage* pUem;

pUem = (UserEventMessage*) event.GetData();

assert(pUem != NULL);

switch (pUem->GetType()) {

case UserEventMessage::kRuntimeStarted:

printf("Sim: runtime thread started!\n");

HandleRuntimeStart();

break;

case UserEventMessage::kRuntimeStopped:

printf("Sim: runtime thread stopped!\n");

HandleRuntimeStop();

break;

case UserEventMessage::kErrorMessage:

{

wxString msg = pUem->GetString();

wxMessageBox(msg, wxT("Android Runtime Error"),

wxOK | wxICON_WARNING, this);

}

break;

case UserEventMessage::kLogMessage:

mpLogWindow->AddLogMessage(pUem->GetLogMessage());

break;

case UserEventMessage::kExternalRuntime:

HandleExternalRuntime(pUem->GetReader(), pUem->GetWriter());

break;

default:

printf("Sim: MESSAGE: unknown UserEventMessage rcvd (type=%d)\n",

pUem->GetType());

break;

}

delete pUem;

}

/*

* The device management thread is up, so the runtime should be fully

* running shortly.

*/

void MainFrame::HandleRuntimeStart(void)

{

mSimRunning = true;

SetStatusText(kStatusRunning, 1);

}

/*

* The device management thread is exiting, so the runtime must be dead.

*/

void MainFrame::HandleRuntimeStop(void)

{

mSimRunning = false;

SetStatusText(kStatusNotRunning, 1);

if (mRestartRequested) {

printf("Sim: restarting runtime\n");

mRestartRequested = false;

SetupPhoneUI(GetSelectedDeviceIndex(), NULL);

if (mpPhoneWindow != NULL)

mpPhoneWindow->GetDeviceManager()->StartRuntime();

}

}

/*

* Handle a connection from an external runtime.

*/

void MainFrame::HandleExternalRuntime(android::Pipe* reader,

android::Pipe* writer)

{

android::MessageStream msgStream;

android::Message msg;

if (IsRuntimeRunning()) {

/*

* Tell the new guy to go away.

*/

if (!msgStream.init(reader, writer, true)) {

fprintf(stderr, "Sim: WARNING: unable to talk to remote runtime\n");

goto bail;

}

printf("Sim: telling external runtime to go away\n");

msg.setCommand(android::Simulator::kCommandGoAway, 0);

msgStream.send(&msg);

} else {

printf("Sim: new external runtime wants to talk to us\n");

/*

* Launch the pieces necessary to talk to this guy.

*/

int id = GetSelectedDeviceIndex();

if (id < 0) {

fprintf(stderr,

"Sim: could not identify currently selected device\n");

goto bail;

}

/* kill existing window, so it pops up and reclaims focus */

if (mpPhoneWindow != NULL) {

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

bool okay;

if (pPrefs->GetBool("refocus-on-restart", &okay) && okay) {

printf("Sim: inducing phone window refocus\n");

mpPhoneWindow->Close(TRUE); // no veto

mpPhoneWindow = NULL;

}

}

SetupPhoneUI(id, NULL);

if (mpPhoneWindow != NULL) {

mpPhoneWindow->GetDeviceManager()->StartRuntime(reader, writer);

} else {

fprintf(stderr, "Sim: ERROR: unable to get runtime going\n");

goto bail;

}

// we don't own these anymore

reader = writer = NULL;

}

bail:

delete reader;

delete writer;

}

/*

* The phone window is about to destroy itself. Get rid of our pointer

* to it, and record its last position so we can create the new one in

* the same place.

*/

void MainFrame::PhoneWindowClosing(int x, int y)

{

Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs();

mpPhoneWindow = NULL;

mPhoneWindowPosn.x = x;

mPhoneWindowPosn.y = y;

pPrefs->SetInt("window-device-x", x);

pPrefs->SetInt("window-device-y", y);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值