#include "wxsheaders.h"
#include "wxswindoweditor.h"
#include "widget.h"
#include <wx/settings.h>
#include <wx/scrolwin.h>
#include <wx/clipbrd.h>
#include "wxspropertiesman.h"
#include "wxspalette.h"
#include "wxsmith.h"
#include "wxsresource.h"
#include "wxsdragwindow.h"
#include "resources/wxswindowres.h"
#include "resources/wxswindowresdataobject.h"
#include "wxswinundobuffer.h"
#include "wxswidgetfactory.h"
wxsWindowEditor::wxsWindowEditor(wxWindow* parent,wxsWindowRes* Resource):
wxsEditor(parent,Resource->GetWxsFile(),Resource),
UndoBuff(new wxsWinUndoBuffer(Resource)),
InsideMultipleChange(false)
{
wxSizer* Sizer = new wxBoxSizer(wxVERTICAL);
Scroll = new wxScrolledWindow(this);
Scroll->SetScrollRate(4,4);
Sizer->Add(Scroll,1,wxGROW);
Scroll->SetScrollRate(4,4);
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
Scroll->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
SetSizer(Sizer);
DragWnd = new wxsDragWindow(Scroll,NULL,Scroll->GetSize());
DragWnd->Hide();
wxFileName Name(Resource->GetWxsFile());
SetTitle(Name.GetFullName());
// Storing current resource data as a base for undo buffer
UndoBuff->StoreChange();
UndoBuff->Saved();
}
wxsWindowEditor::~wxsWindowEditor()
{
wxsUnselectRes(GetResource());
KillPreview();
delete UndoBuff;
}
static void WidgetRefreshReq(wxWindow* Wnd)
{
if ( !Wnd ) return;
Wnd->Refresh(true);
wxWindowList& List = Wnd->GetChildren();
for ( wxWindowListNode* Node = List.GetFirst(); Node; Node = Node->GetNext() )
{
wxWindow* Win = Node->GetData();
WidgetRefreshReq(Win);
}
}
void wxsWindowEditor::BuildPreview()
{
Scroll->SetSizer(NULL);
Freeze();
KillPreview();
// Creating new sizer
wxsWidget* TopWidget = GetWinRes()->GetRootWidget();
wxWindow* TopPreviewWindow = TopWidget ? TopWidget->CreatePreview(Scroll,this) : NULL;
if ( TopPreviewWindow )
{
wxSizer* NewSizer = new wxGridSizer(1);
NewSizer->Add(TopPreviewWindow,0,/*wxALIGN_CENTRE_VERTICAL|wxALIGN_CENTRE_HORIZONTAL|*/wxALL,10);
Scroll->SetVirtualSizeHints(1,1);
Scroll->SetSizer(NewSizer);
NewSizer->SetVirtualSizeHints(Scroll);
Layout();
wxSize Virtual = Scroll->GetVirtualSize();
wxSize Real = Scroll->GetSize();
wxSize Drag(Virtual.GetWidth() > Real.GetWidth() ? Virtual.GetWidth() : Real.GetWidth(),
Virtual.GetHeight() > Real.GetHeight() ? Virtual.GetHeight() : Real.GetHeight());
// Waiting to reposition and resize all widgets
// FIXME (SpOoN#1#): Don't ever use wxYield, just add pending event and do all required stuff in it's handler
::wxYield();
DragWnd->SetSize(Drag);
DragWnd->NotifySizeChange(Drag);
DragWnd->SetWidget(TopWidget);
DragWnd->Show();
}
Thaw();
}
void wxsWindowEditor::KillPreview()
{
Scroll->SetSizer(NULL);
GetWinRes()->GetRootWidget()->KillPreview();
DragWnd->Hide();
}
void wxsWindowEditor::OnMouseClick(wxMouseEvent& event)
{
wxsPropertiesMan::Get()->SetActiveWidget(GetWinRes()->GetRootWidget());
}
void wxsWindowEditor::OnSelectWidget(wxsEvent& event)
{
if ( DragWnd )
{
DragWnd->ProcessEvent(event);
}
}
void wxsWindowEditor::OnUnselectWidget(wxsEvent& event)
{
if ( DragWnd )
{
DragWnd->ProcessEvent(event);
}
}
bool wxsWindowEditor::Close()
{
return wxsEditor::Close();
}
bool wxsWindowEditor::Save()
{
GetWinRes()->Save();
return true;
}
bool wxsWindowEditor::GetModified()
{
return GetWinRes()->GetModified();
}
void wxsWindowEditor::SetModified(bool modified)
{
GetWinRes()->SetModified(modified);
if ( GetWinRes()->GetModified() )
{
SetTitle(_T("*") + GetShortName());
}
else
{
SetTitle(GetShortName());
}
}
bool wxsWindowEditor::CanUndo()
{
return UndoBuff->CanUndo();
}
bool wxsWindowEditor::CanRedo()
{
return UndoBuff->CanRedo();
}
void wxsWindowEditor::Undo()
{
wxsWidget* NewRoot = UndoBuff->Undo();
if ( !NewRoot ) return;
if ( !GetWinRes()->ChangeRootWidget(NewRoot) )
{
DebLog(_("wxSmith ERROR: Something wrong with undo buffer !!!"));
wxsKILL(NewRoot);
}
SetModified(UndoBuff->IsModified());
}
void wxsWindowEditor::Redo()
{
wxsWidget* NewRoot = UndoBuff->Redo();
if ( !NewRoot ) return;
if ( !GetWinRes()->ChangeRootWidget(NewRoot) )
{
DebLog(_("wxSmith ERROR: Something wrong with undo buffer !!!"));
wxsKILL(NewRoot);
}
SetModified(UndoBuff->IsModified());
}
bool wxsWindowEditor::CanCut()
{
return DragWnd && DragWnd->GetMultipleSelCount();
}
bool wxsWindowEditor::CanCopy()
{
return DragWnd && DragWnd->GetMultipleSelCount();
}
bool wxsWindowEditor::CanPaste()
{
if ( !wxTheClipboard->Open() ) return false;
bool Res = wxTheClipboard->IsSupported(wxsDF_WIDGET);
// FIXME (SpOoN#1#): Add support for text (XRC) data
wxTheClipboard->Close();
return Res;
}
void wxsWindowEditor::Cut()
{
// Almost all selected widgets will be added into clipboard
// but with one exception - widget won't be added if parent of this
// widget at any level is also selected
std::vector<wxsWidget*> Widgets;
GetSelectionNoChildren(Widgets);
if ( !DragWnd ) return;
if ( !wxTheClipboard->Open() ) return;
wxsWindowResDataObject* Data = new wxsWindowResDataObject;
int Cnt = (int)Widgets.size();
for ( int i=0; i<Cnt; i++ )
{
Data->AddWidget(Widgets[i]);
}
wxTheClipboard->SetData(Data);
wxTheClipboard->Close();
// Removing widgets copied into clipboard
KillPreview();
for ( int i=0; i<Cnt; i++ )
{
// Can not delete top-most widget
if ( Widgets[i]->GetParent() )
{
wxsKILL(Widgets[i]);
}
}
BuildPreview();
}
void wxsWindowEditor::Copy()
{
// Almost all selected widgets will be added into clipboard
// but with one exception - widget won't be added if parent of this
// widget at any level is also selected
std::vector<wxsWidget*> Widgets;
GetSelectionNoChildren(Widgets);
if ( !DragWnd ) return;
if ( !wxTheClipboard->Open() ) return;
wxsWindowResDataObject* Data = new wxsWindowResDataObject;
int Cnt = (int)Widgets.size();
for ( int i=0; i<Cnt; i++ )
{
Data->AddWidget(Widgets[i]);
}
wxTheClipboard->SetData(Data);
wxTheClipboard->Close();
}
void wxsWindowEditor::Paste()
{
if ( !wxTheClipboard->Open() ) return;
wxsWindowResDataObject Data;
if ( wxTheClipboard->GetData(Data) )
{
wxsWidget* RelativeTo = DragWnd->GetSelection();
int InsertionType = wxsPalette::Get()->GetInsertionType();
if ( !RelativeTo )
{
InsertionType = wxsPalette::itInto;
RelativeTo = GetWinRes()->GetRootWidget();
if ( RelativeTo->GetChildCount() == 1 &&
RelativeTo->GetChild(0)->GetInfo().Sizer )
{
RelativeTo = RelativeTo->GetChild(0);
}
}
int Cnt = Data.GetWidgetCount();
if ( Cnt )
{
StartMultipleChange();
for ( int i=0; i<Cnt; i++ )
{
wxsWidget* Insert = Data.BuildWidget(GetWinRes(),i);
if ( Insert )
{
switch ( InsertionType )
{
case wxsPalette::itAfter:
InsertAfter(Insert,RelativeTo);
RelativeTo = Insert;
break;
case wxsPalette::itBefore:
InsertBefore(Insert,RelativeTo);
break;
case wxsPalette::itInto:
InsertInto(Insert,RelativeTo);
break;
}
}
}
EndMultipleChange();
// FIXME (SpOoN#1#): Updating base properties probably won't work properly
GetWinRes()->CheckBaseProperties(true,NULL);
GetWinRes()->NotifyChange();
}
}
wxTheClipboard->Close();
}
void wxsWindowEditor::GetSelectionNoChildren(std::vector<wxsWidget*>& Vector)
{
DragWnd->GetSelectionNoChildren(Vector);
}
bool wxsWindowEditor::StartMultipleChange()
{
if ( InsideMultipleChange ) return false;
InsideMultipleChange = true;
KillPreview();
return true;
}
bool wxsWindowEditor::EndMultipleChange()
{
if ( !InsideMultipleChange ) return false;
InsideMultipleChange = false;
BuildPreview();
wxsTREE()->Refresh();
return true;
}
bool wxsWindowEditor::InsertBefore(wxsWidget* New,wxsWidget* Ref)
{
if ( !Ref )
{
Ref = DragWnd->GetSelection();
}
if ( !Ref )
{
wxsKILL(New);
return false;
}
if ( !InsideMultipleChange )
{
KillPreview();
}
wxsWidget* Parent = Ref->GetParent();
int Index;
bool Ret;
if ( !Parent || (Index=Parent->FindChild(Ref)) < 0 || Parent->AddChild(New,Index) < 0 )
{
wxsKILL(New);
Ret = false;
}
else
{
// Adding this new item into resource tree
New->BuildTree(wxsTREE(),Parent->TreeId,Index);
Ret = true;
}
if ( !InsideMultipleChange )
{
wxsTREE()->Refresh();
BuildPreview();
}
return Ret;
}
bool wxsWindowEditor::InsertAfter(wxsWidget* New,wxsWidget* Ref)
{
if ( !Ref )
{
Ref = DragWnd->GetSelection();
}
if ( !Ref )
{
wxsKILL(New);
return false;
}
if ( !InsideMultipleChange )
{
KillPreview();
}
wxsWidget* Parent = Ref->GetParent();
int Index;
bool Ret;
if ( !Parent || (Index=Parent->FindChild(Ref)) < 0 || Parent->AddChild(New,Index+1) < 0 )
{
wxsKILL(New);
Ret = false;
}
else
{
// Adding this new item into resource tree
New->BuildTree(wxsTREE(),Parent->TreeId,Index+1);
Ret = true;
}
if ( !InsideMultipleChange )
{
wxsTREE()->Refresh();
BuildPreview();
}
return Ret;
}
bool wxsWindowEditor::InsertInto(wxsWidget* New,wxsWidget* Ref)
{
if ( !Ref )
{
Ref = DragWnd->GetSelection();
}
if ( !Ref )
{
wxsKILL(New);
return false;
}
if ( !InsideMultipleChange )
{
KillPreview();
}
bool Ret;
if ( Ref->AddChild(New) < 0 )
{
wxsKILL(New);
Ret = false;
}
else
{
New->BuildTree(wxsTREE(),Ref->TreeId);
Ret = true;
}
if ( !InsideMultipleChange )
{
wxsTREE()->Refresh();
BuildPreview();
}
return Ret;
}
BEGIN_EVENT_TABLE(wxsWindowEditor,wxsEditor)
EVT_LEFT_DOWN(wxsWindowEditor::OnMouseClick)
EVT_SELECT_WIDGET(wxsWindowEditor::OnSelectWidget)
EVT_UNSELECT_WIDGET(wxsWindowEditor::OnUnselectWidget)
END_EVENT_TABLE()
syntax highlighted by Code2HTML, v. 0.9.1