#include "wxsheaders.h"
#include "wxseventseditor.h"
#include "widget.h"
#include "wxswidgetevents.h"
#include "resources/wxswindowres.h"
#include <editormanager.h>
#define NoneStr _("-- None --")
#define AddNewStr _("-- Add new handler --")
wxsEventsEditor::wxsEventsEditor(wxWindow* Parent,wxsWidget* Widget):
wxPropertyGrid(Parent,-1,wxDefaultPosition,wxDefaultSize)
{
SetWidget(Widget);
}
void wxsEventsEditor::SetWidget(wxsWidget* _Widget)
{
Widget = _Widget;
Events = _Widget->GetEvents();
Res = _Widget->GetResource();
Proj = Res->GetProject();
SourceFile = Proj->GetProjectFileName(Res->GetSourceFile());
HeaderFile = Proj->GetProjectFileName(Res->GetHeaderFile());
ClassName = Res->GetClassName();
BuildPropertyGrid();
}
wxsEventsEditor::~wxsEventsEditor()
{
}
void wxsEventsEditor::OnPropertyChanged(wxPropertyGridEvent& event)
{
ReadPropertyGrid();
Res->UpdateEventTable();
}
void wxsEventsEditor::BuildPropertyGrid(bool UpdateOnly)
{
UpdateOnly = false; // There's something wrong when updating
if ( !UpdateOnly )
{
Clear();
}
int Cnt = Events->GetEventCount();
for ( int i=0; i<Cnt; i++ )
{
wxsEventDesc* Event = Events->GetEvent(i);
wxArrayString Functions;
FindFunctions(Event->EventTypeName,Functions);
wxPGConstants Const;
int Index = 0;
Const.Add(NoneStr,0);
Const.Add(AddNewStr,1);
for ( int j=0; j<(int)Functions.Count(); j++ )
{
Const.Add(Functions[j],j+2);
if ( Functions[j] == Event->FunctionName )
{
Index = j+2;
}
}
if ( UpdateOnly )
{
wxPGId Id = GetPropertyByLabel(Event->EventEntry);
if ( Id.IsOk() )
{
SetPropertyChoices(Id,Const);
SetPropertyValue(Id,Index);
}
}
else
{
Append(wxEnumProperty(Event->EventEntry,wxPG_LABEL,Const,Index));
}
}
}
void wxsEventsEditor::ReadPropertyGrid()
{
bool NeedUpdate = false;
int Cnt = Events->GetEventCount();
for ( int i = 0; i < Cnt; ++i )
{
wxsEventDesc* Event = Events->GetEvent(i);
wxPGId Id = GetPropertyByLabel(Event->EventEntry);
if ( Id.IsOk() )
{
wxString Selection = GetPropertyValueAsString(Id);
if ( Selection == NoneStr )
{
Event->FunctionName = _T("");
}
else if ( Selection == AddNewStr )
{
Event->FunctionName = GetNewFunction(Event);
NeedUpdate = true;
}
else
{
Event->FunctionName = Selection;
}
}
}
if ( NeedUpdate )
{
UpdatePropertyGrid();
}
}
void wxsEventsEditor::FindFunctions(const wxString& EventType,wxArrayString& Array)
{
wxString Code = wxsCoder::Get()->GetCode( HeaderFile,
wxString::Format(wxsBHeaderF("Handlers"),ClassName.c_str()) );
// Basic parsing
for(;;)
{
// Searching for void statement - it may begin new fuunction declaration
int Pos = Code.Find(_T("void"));
if ( Pos == -1 ) break;
// Removing all before function name
Code.Remove(0,Pos+4).Trim(false);
// Getting function name
Pos = 0;
while ( (int)Code.Length() > Pos )
{
wxChar First = Code.GetChar(Pos);
if ( ( First<_T('A') || First>_T('Z') ) &&
( First<_T('a') || First>_T('z') ) &&
( First<_T('0') || First>_T('9') ) )
{
break;
}
Pos++;
}
wxString NewFunctionName = Code.Mid(0,Pos);
Code.Remove(0,Pos).Trim(false);
if ( !Code.Length() ) break;
// Parsing arguments
if ( Code.GetChar(0) != _T('(') ) continue;
Code.Remove(0,1).Trim(false);
if ( !Code.Length() ) break;
// Getting argument type
Pos = 0;
while ( (int)Code.Length() > Pos )
{
wxChar First = Code.GetChar(Pos);
if ( ( First<_T('A') || First>_T('Z') ) &&
( First<_T('a') || First>_T('z') ) &&
( First<_T('0') || First>_T('9') ) )
{
break;
}
Pos++;
}
wxString NewEventType = Code.Mid(0,Pos);
Code.Remove(0,Pos).Trim(false);
if ( !Code.Length() ) break;
// Checking if the rest of declaratin is valid
if ( Code.GetChar(0) != _T('&') ) continue;
Code.Remove(0,1).Trim(false);
if ( !Code.Length() ) break;
// Skipping argument name
Pos = 0;
while ( (int)Code.Length() > Pos )
{
wxChar First = Code.GetChar(Pos);
if ( ( First<_T('A') || First>_T('Z') ) &&
( First<_T('a') || First>_T('z') ) &&
( First<_T('0') || First>_T('9') ) )
{
break;
}
Pos++;
}
Code.Remove(0,Pos).Trim(false);
if ( !Code.Length() ) break;
if ( Code.GetChar(0) != _T(')') ) continue;
Code.Remove(0,1).Trim(false);
if ( !Code.Length() ) break;
if ( Code.GetChar(0) != _T(';') ) continue;
Code.Remove(0,1).Trim(false);
if ( NewFunctionName.Length() == 0 || NewEventType.Length() == 0 ) continue;
// We got new function, checking event type and adding to array
if ( !EventType.Length() || EventType == NewEventType )
{
Array.Add(NewFunctionName);
}
}
}
wxString wxsEventsEditor::GetFunctionProposition(wxsEventDesc* Event)
{
// Creating proposition of new function name
wxString NewNameBase;
NewNameBase.Printf(_T("On%s%s"),Widget->GetBaseParams().VarName.c_str(),Event->NewFuncNameBase.c_str());
int Suffix = 0;
wxArrayString Functions;
FindFunctions(_T(""),Functions);
wxString NewName = NewNameBase;
while ( Functions.Index(NewName) != wxNOT_FOUND )
{
NewName = NewNameBase;
NewName << ++Suffix;
}
return NewName;
}
wxString wxsEventsEditor::GetNewFunction(wxsEventDesc* Event)
{
wxString Name = GetFunctionProposition(Event);
for (;;)
{
Name = ::wxGetTextFromUser(_("Enter name for new handler:"),_("New handler"),Name);
if ( !Name.Length() ) return _T("");
if ( !ValidateIdentifier(Name) )
{
wxMessageBox(_("Invalid name"));
continue;
}
wxArrayString Functions;
FindFunctions(_T(""),Functions);
if ( Functions.Index(Name) != wxNOT_FOUND )
{
wxMessageBox(_("Handler with this name already exists"));
continue;
}
break;
}
// Creating new function
if ( !CreateNewFunction(Event,Name) )
{
wxMessageBox(_("Couldn't add new handler"));
return _T("");
}
return Name;
}
bool wxsEventsEditor::CreateNewFunction(wxsEventDesc* Event,const wxString& NewFunctionName)
{
wxString DeclarationsHeader;
DeclarationsHeader.Printf(wxsBHeaderF("Handlers"),ClassName.c_str());
wxString Declarations = wxsCoder::Get()->GetCode(HeaderFile,DeclarationsHeader);
if ( Declarations.Length() == 0 ) return false;
Declarations << _T("void ") << NewFunctionName << _T('(');
Declarations << Event->EventTypeName << _T("& event);\n");
Declarations.Append(_T(' '),2*4);
wxsCoder::Get()->AddCode(HeaderFile,DeclarationsHeader,Declarations,true);
Res->UpdateEventTable();
cbEditor* Editor = Manager::Get()->GetEditorManager()->Open(SourceFile);
if ( !Editor ) return false;
wxString NewFunctionCode;
NewFunctionCode.Printf(
_T("\n")
_T("void %s::%s(%s& event)\n")
_T("{\n")
_T("}\n"),
Res->GetClassName().c_str(),
NewFunctionName.c_str(),
Event->EventTypeName.c_str());
cbStyledTextCtrl* Ctrl = Editor->GetControl();
Ctrl->DocumentEnd();
Ctrl->AddText(NewFunctionCode);
Ctrl->LineUp();
Ctrl->LineUp();
Ctrl->LineEnd();
Editor->SetModified();
return true;
}
BEGIN_EVENT_TABLE(wxsEventsEditor,wxPropertyGrid)
EVT_PG_CHANGED(-1,wxsEventsEditor::OnPropertyChanged)
END_EVENT_TABLE()
syntax highlighted by Code2HTML, v. 0.9.1