/home/enzo/treballs/fib/pfc/nanocomp/src/layoutView.cpp

Go to the documentation of this file.
00001 /*
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *   This program is distributed in the hope that it will be useful,       *
00009  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00010  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00011  *   GNU General Public License for more details.                          *
00012  *                                                                         *
00013  *   You should have received a copy of the GNU General Public License     *
00014  *   along with this program; if not, write to the                         *
00015  *   Free Software Foundation, Inc.,                                       *
00016  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00017                                                                           */
00018 // $Revision: 1.27 $
00019 
00020 #include "layoutView.hpp"
00021 
00022 #include <wx/statline.h>
00023 #include "resources/fileopen.xpm"
00024 #include "resources/filesave.xpm"
00025 #include "resources/filesaveas.xpm"
00026 #include "resources/new.xpm"
00027 #include "resources/forward.xpm"
00028 
00029 enum
00030 {
00031     ID_TEXT_NAME = 0,
00032     ID_TEXT_DESCRIPTION,
00033     ID_BUTTON_NEW,
00034     ID_BUTTON_OPEN,
00035     ID_BUTTON_SAVE,
00036     ID_BUTTON_SAVEAS,
00037     ID_BUTTON_ASSIGNINPUT,
00038     ID_BUTTON_ASSIGNOUTPUT,
00039     ID_BUTTON_PREPARE,
00040     ID_BUTTON_START,
00041     ID_LISTTABLES,
00042     ID_LISTRULES,
00043     ID_LISTFPS,
00044     ID_LISTINPUTS,
00045     ID_LISTOUTPUTS,
00046     ID_CANVAS
00047 };
00048 
00049 
00050 BEGIN_EVENT_TABLE(LayoutView, wxPanel)
00051     EVT_LAYOUT_CANVAS  (ID_CANVAS,  LayoutView::OnClick)
00052     EVT_BUTTON  (ID_BUTTON_NEW, LayoutView::OnNew)
00053     EVT_BUTTON  (ID_BUTTON_OPEN, LayoutView::OnOpen)
00054     EVT_BUTTON  (ID_BUTTON_SAVE, LayoutView::OnSave)
00055     EVT_BUTTON  (ID_BUTTON_SAVEAS, LayoutView::OnSaveAs)
00056     EVT_BUTTON  (ID_BUTTON_ASSIGNINPUT, LayoutView::OnAssignInput)
00057     EVT_BUTTON  (ID_BUTTON_ASSIGNOUTPUT, LayoutView::OnAssignOutput)
00058     EVT_BUTTON  (ID_BUTTON_PREPARE, LayoutView::OnPrepare)
00059     EVT_BUTTON  (ID_BUTTON_START, LayoutView::OnStart)
00060     EVT_LISTBOX (ID_LISTTABLES, LayoutView::OnTableSelected)
00061     EVT_LISTBOX (ID_LISTINPUTS, LayoutView::OnInputSelected)
00062     EVT_LISTBOX (ID_LISTOUTPUTS, LayoutView::OnOutputSelected)
00063     EVT_CHECKLISTBOX (ID_LISTTABLES, LayoutView::OnTableChecked)
00064     EVT_CHECKLISTBOX (ID_LISTRULES, LayoutView::OnRuleChecked)
00065     EVT_CHECKLISTBOX (ID_LISTFPS, LayoutView::OnFPChecked)
00066     EVT_KEY_UP (LayoutView::OnKeyPressed)
00067 END_EVENT_TABLE()
00068 
00069 
00071 
00076 LayoutView::LayoutView(wxWindow* parent, wxWindowID id, LayoutManager *controller)
00077     :wxPanel(parent, id)
00078 {
00079     this->controller = controller;
00080     initControls();
00081     initSizers();
00082     controller->setView(this);
00083     buttonPrepareSimulation->Enable(true);
00084     buttonStartSimulation->Enable(false);
00085 }
00086 
00087 
00089 LayoutView::~LayoutView()
00090 {
00091 }
00092 
00093 
00095 void LayoutView::initControls()
00096 {
00097     //Buttons
00098     wxBitmap newBitmap(wxBITMAP(new));
00099     wxBitmap saveBitmap(wxBITMAP(filesave));
00100     wxBitmap saveAsBitmap(wxBITMAP(filesaveas));
00101     wxBitmap openBitmap(wxBITMAP(fileopen));
00102     wxBitmap assignBitmap(wxBITMAP(forward));
00103     buttonNew = new wxBitmapButton(this, ID_BUTTON_NEW, newBitmap);
00104     buttonNew->SetToolTip(_("New layout"));
00105     buttonOpen = new wxBitmapButton(this, ID_BUTTON_OPEN, openBitmap);
00106     buttonOpen->SetToolTip(_("Open a layout file"));
00107     buttonSave = new wxBitmapButton(this, ID_BUTTON_SAVE, saveBitmap);
00108     buttonSave->SetToolTip(_("Save selected layout to a file"));
00109     buttonSaveAs = new wxBitmapButton(this, ID_BUTTON_SAVEAS, saveAsBitmap);
00110     buttonSaveAs->SetToolTip(_("Save selected layout to new a file"));
00111     buttonAssignInput = new wxBitmapButton(this, ID_BUTTON_ASSIGNINPUT, assignBitmap);
00112     buttonAssignInput->SetToolTip(_("Assign input to layout"));
00113     buttonAssignOutput = new wxBitmapButton(this, ID_BUTTON_ASSIGNOUTPUT, assignBitmap);
00114     buttonAssignOutput->SetToolTip(_("Assign output to layout"));
00115     buttonSave->Enable(false);
00116     buttonSaveAs->Enable(false);
00117     buttonAssignInput->Enable(false);
00118     buttonAssignOutput->Enable(false);
00119     buttonPrepareSimulation = new wxButton(this, ID_BUTTON_PREPARE, _("Check simulation"));
00120     buttonStartSimulation = new wxButton(this, ID_BUTTON_START, _("Begin simulation"));
00121     
00122     //Other controls
00123     listTables = new wxCheckListBox(this, ID_LISTTABLES);
00124     listRules = new wxCheckListBox(this, ID_LISTRULES);
00125     listFPs = new wxCheckListBox(this, ID_LISTFPS);
00126     listInputs = new wxListBox(this, ID_LISTINPUTS);
00127     listOutputs = new wxListBox(this, ID_LISTOUTPUTS);
00128     canvas = new LayoutCanvas(this, ID_CANVAS, Grid());
00129 }
00130 
00131 
00133 void LayoutView::initSizers()
00134 {
00135    //Main Sizer
00136     wxBoxSizer *mainSizer = new wxBoxSizer(wxHORIZONTAL);
00137 
00138         //TTList and I/O sizer
00139         wxBoxSizer *listsSizer = new wxBoxSizer(wxVERTICAL);
00140             
00141             //List sizer
00142             wxStaticBoxSizer *TTListSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Truth Table list"));
00143             TTListSizer->Add(listTables, 1, wxEXPAND | wxALL, 1);
00144             wxBoxSizer *IOSizer = new wxBoxSizer(wxVERTICAL);
00145             //wxBoxSizer *inputsSizer = new wxBoxSizer(wxVERTICAL);
00146             wxBoxSizer *listButtonInputSizer = new wxBoxSizer(wxHORIZONTAL);
00147             //inputsSizer->Add(labelInputs, 0, wxEXPAND | wxALL | wxALIGN_CENTER, 1);
00148             listButtonInputSizer->Add(listInputs, 1, wxEXPAND | wxALL, 1);
00149             listButtonInputSizer->Add(buttonAssignInput, 0, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00150             //inputsSizer->Add(listButtonInputSizer, 0, wxEXPAND | wxALL | wxALIGN_CENTER, 1);
00151             //inputsSizer->Add(listInputs, 1, wxEXPAND | wxALL, 1);
00152             //inputsSizer->Add(buttonAssignInput, 0, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00153             //IOSizer->Add(inputsSizer, 1, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00154             IOSizer->Add(listButtonInputSizer, 1, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00155             
00156             //wxBoxSizer *outputsSizer = new wxBoxSizer(wxVERTICAL);
00157             wxBoxSizer *listButtonOutputSizer = new wxBoxSizer(wxHORIZONTAL);
00158             //outputsSizer->Add(labelOutputs, 0, wxEXPAND | wxALL | wxALIGN_CENTER, 1);
00159             listButtonOutputSizer->Add(listOutputs, 1, wxEXPAND | wxALL, 1);
00160             listButtonOutputSizer->Add(buttonAssignOutput, 0, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00161             //outputsSizer->Add(listButtonOutputSizer, 0, wxEXPAND | wxALL | wxALIGN_CENTER, 1);
00162             //IOSizer->Add(outputsSizer, 1, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00163             IOSizer->Add(listButtonOutputSizer, 1, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00164             
00165             TTListSizer->Add(IOSizer, 1, wxEXPAND | wxALL | wxALIGN_CENTER, 1);
00166             
00167             wxStaticBoxSizer *RuleListSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Rule list"));
00168             RuleListSizer->Add(listRules, 1, wxEXPAND | wxALL, 1);
00169             
00170             wxStaticBoxSizer *FPListSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Forbidden Pattern list"));
00171             FPListSizer->Add(listFPs, 1, wxEXPAND | wxALL, 1);
00172             
00173         wxBoxSizer *ruleFPSizer = new wxBoxSizer(wxHORIZONTAL);
00174         ruleFPSizer->Add(RuleListSizer, 1, wxEXPAND | wxALL, 1);
00175         ruleFPSizer->Add(FPListSizer, 1, wxEXPAND | wxALL, 1);
00176         listsSizer->Add(TTListSizer, 1, wxEXPAND | wxALL, 1);
00177         listsSizer->Add(ruleFPSizer, 1, wxEXPAND | wxALL, 1);
00178         
00179             //Layouts sizer
00180             wxStaticBoxSizer *layoutSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Layout"));
00181             layoutSizer->Add(canvas, 1, wxEXPAND | wxALL | wxALIGN_CENTER, 2);
00182             
00183             //Buttons sizer
00184                 wxBoxSizer *buttonSizer = new wxBoxSizer(wxVERTICAL);
00185                 buttonSizer->Add(buttonNew, 0, wxEXPAND | wxALL);
00186                 buttonSizer->Add(buttonOpen, 0, wxEXPAND | wxALL);
00187                 buttonSizer->Add(buttonSave, 0, wxEXPAND | wxALL);
00188                 buttonSizer->Add(buttonSaveAs, 0, wxEXPAND | wxALL);
00189             layoutSizer->Add(buttonSizer, 0, wxSHAPED | wxALL | wxALIGN_CENTER, 1);
00190             
00191             //Simularion sizer
00192             wxStaticBoxSizer *simulationSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Simulation"));
00193             simulationSizer->AddStretchSpacer(1);
00194             simulationSizer->Add(buttonPrepareSimulation, 0, wxSHAPED | wxALIGN_CENTER, 1);
00195             simulationSizer->AddStretchSpacer(1);
00196             simulationSizer->Add(buttonStartSimulation, 0, wxSHAPED | wxALIGN_CENTER, 1);
00197             simulationSizer->AddStretchSpacer(1);
00198             
00199             //Right sizer
00200             wxBoxSizer *layoutSimulationSizer = new wxBoxSizer(wxVERTICAL);
00201             layoutSimulationSizer->Add(layoutSizer, 2, wxEXPAND | wxALL, 1);
00202             layoutSimulationSizer->Add(simulationSizer, 1, wxEXPAND | wxALL, 1);
00203             
00204         //listLayoutSizer->Add(layoutSizer, 3, wxEXPAND | wxALL, 5);
00205     
00206     mainSizer->Add(listsSizer, 1, wxEXPAND | wxALL, 1);
00207     mainSizer->Add(layoutSimulationSizer, 1, wxEXPAND | wxALL, 1);
00208 
00209     SetSizer(mainSizer);
00210 }
00211 
00212 
00214 
00217 void LayoutView::OnClick(LayoutCanvasEvent &event)
00218 {
00219     controller->cellChanged(event.getX(), event.getY());
00220 }
00221 
00222 
00224 
00227 void LayoutView::OnNew(wxCommandEvent &event)
00228 {
00229     int width;
00230     int height;
00231     int inputs;
00232     int outputs;
00233     
00234     //The user is asked for the information of the new space
00235     wxNumberEntryDialog widthDialog(this,
00236     wxEmptyString,
00237         _("Insert the layout width"),
00238         _("New Layout"),
00239         1, 1, 100);
00240     if (widthDialog.ShowModal() == wxID_OK)
00241     {
00242         width = (int)(widthDialog.GetValue());
00243     }
00244     else
00245     {
00246         return;
00247     }
00248     
00249     wxNumberEntryDialog heightDialog(this,
00250     wxEmptyString,
00251         _("Insert the layout height"),
00252         _("New Layout"),
00253         1, 1, 100);
00254     
00255     if (heightDialog.ShowModal() == wxID_OK)
00256     {
00257         height = (int)(heightDialog.GetValue());
00258     }
00259     else
00260     {
00261         return;
00262     }
00263     
00264     //TODO: comprovar inputs i outputs vālids
00265     wxNumberEntryDialog inputsDialog(this,
00266     wxEmptyString,
00267         _("Insert the layout input number"),
00268         _("New Layout"),
00269         1, 1, 100);
00270     
00271     if (inputsDialog.ShowModal() == wxID_OK)
00272     {
00273         inputs = (int)(inputsDialog.GetValue());
00274     }
00275     else
00276     {
00277         return;
00278     }
00279     
00280     wxNumberEntryDialog outputsDialog(this,
00281     wxEmptyString,
00282         _("Insert the layout output number"),
00283         _("New Layout"),
00284         1, 1, 100);
00285     
00286     if (outputsDialog.ShowModal() == wxID_OK)
00287     {
00288         outputs = (int)(outputsDialog.GetValue());
00289         controller->newLayout(width, height, inputs, outputs);
00290         buttonSave->Enable(true);
00291         buttonSaveAs->Enable(true);
00292     }
00293     else
00294     {
00295         return;
00296     }
00297 }
00298 
00299 
00301 
00306 void LayoutView::updateGrids(Grid grid, bool changed)
00307 {
00308     canvas->setGrid(grid, changed);
00309     buttonSave->Enable(true);
00310     buttonSaveAs->Enable(true);
00311 }
00312 
00313 
00315 
00318 void LayoutView::updateTTList(map<wxString, bool> tables)
00319 {
00320     wxArrayString strings;
00321     //Add strings
00322     for (map<wxString, bool>::iterator i = tables.begin(); i != tables.end(); i++)
00323     {
00324         strings.Add((*i).first);
00325     }
00326     listTables->Set(strings);
00327     
00328     //Check strings
00329     for (int i = 0; i < listTables->GetCount(); i++)
00330     {
00331         listTables->Check(i, tables[listTables->GetString(i)]);
00332     }
00333 }
00334 
00335 
00337 
00340 void LayoutView::updateFPList(map<unsigned int, bool> FPs)
00341 {
00342     wxArrayString strings;
00343     //Add strings
00344     for (map<unsigned int, bool>::iterator i = FPs.begin(); i != FPs.end(); i++)
00345     {
00346         strings.Add(wxString::Format(_("Pattern %d"), (*i).first));
00347     }
00348     listFPs->Set(strings);
00349     
00350     unsigned long int temp;
00351     //Check strings
00352     for (int i = 0; i < listFPs->GetCount(); i++)
00353     {
00354         listFPs->GetString(i).Mid(8).ToULong(&temp);
00355         listFPs->Check(i, FPs[temp]);
00356     }
00357 }
00358 
00359 
00361 
00364 void LayoutView::updateRuleList(map<unsigned int, bool> rules)
00365 {
00366     wxArrayString strings;
00367     //Add strings
00368     for (map<unsigned int, bool>::iterator i = rules.begin(); i != rules.end(); i++)
00369     {
00370         strings.Add(wxString::Format(_("Rule %d"), (*i).first));
00371     }
00372     listRules->Set(strings);
00373     
00374     unsigned long int temp;
00375     //Check strings
00376     for (int i = 0; i < listRules->GetCount(); i++)
00377     {
00378         listRules->GetString(i).Mid(4).ToULong(&temp);
00379         listRules->Check(i, rules[temp]);
00380     }
00381 }
00382 
00383 
00385 
00388 void LayoutView::selectTable(wxString table)
00389 {
00390     int item = listTables->FindString(table);
00391     if (item != wxNOT_FOUND)
00392     {
00393         listTables->SetSelection(item);
00394     }
00395 }
00396 
00397 
00399 
00402 void LayoutView::errorMsg(wxString message)
00403 {
00404     wxMessageDialog dialog(this,
00405             message,
00406             _("Error"), 
00407             wxOK | wxICON_ERROR); 
00408     dialog.ShowModal();
00409 }
00410 
00411 
00413 
00416 void LayoutView::OnOpen(wxCommandEvent& event)
00417 {
00418     controller->openFile();
00419 }
00420 
00421 
00423 
00427 bool LayoutView::msgYesNo(wxString message)
00428 {
00429     wxMessageDialog dialog(this,
00430             message,
00431             _("Question"), 
00432             wxYES | wxNO); 
00433     return (dialog.ShowModal() == wxID_YES);
00434 }
00435 
00436 
00438 
00441 void LayoutView::OnSave(wxCommandEvent& event)
00442 {
00443     controller->saveFile();
00444 }
00445 
00446 
00448 
00451 void LayoutView::OnSaveAs(wxCommandEvent& event)
00452 {
00453     controller->saveFileAs();
00454 }
00455 
00456 
00458 
00461 void LayoutView::OnTableSelected(wxCommandEvent &event)
00462 {
00463     if (event.IsSelection())
00464     {
00465        controller->tableSelected(event.GetString());
00466     }
00467 }
00468 
00469 
00471 
00474 void LayoutView::OnTableChecked(wxCommandEvent &event)
00475 {
00476    controller->tableChecked(listTables->GetString(event.GetSelection()), listTables->IsChecked(event.GetSelection()));
00477 }
00478 
00479 
00481 
00484 void LayoutView::updateInputList(wxArrayString strings)
00485 {
00486     listInputs->Set(strings);
00487     buttonAssignInput->Enable(strings.size() > 0);
00488     if (strings.size() > 0)
00489     {
00490         listInputs->SetSelection(0);
00491     }
00492 }
00493 
00494 
00496 
00499 void LayoutView::updateOutputList(wxArrayString strings)
00500 {
00501     listOutputs->Set(strings);
00502     buttonAssignOutput->Enable(strings.size() > 0);
00503     if (strings.size() > 0)
00504     {
00505         listOutputs->SetSelection(0);
00506     }
00507 }
00508 
00509 
00511 
00514 void LayoutView::OnAssignInput(wxCommandEvent &event)
00515 {
00516     canvas->setVisible(false, false, true, false, false);
00517     onlyAssign(false);
00518     controller->assignInput();
00519     //This needs to be done for the escape event
00520     SetFocusIgnoringChildren();
00521 }
00522 
00523 
00525 
00528 void LayoutView::OnAssignOutput(wxCommandEvent &event)
00529 {
00530     canvas->setVisible(false, false, false, true, false);
00531     onlyAssign(false);
00532     controller->assignOutput();
00533     //This needs to be done for the escape event
00534     SetFocusIgnoringChildren();
00535 }
00536 
00537 
00539 
00545 void LayoutView::onlyAssign(bool enable)
00546 {
00547     buttonNew->Enable(enable);
00548     buttonOpen->Enable(enable);
00549     buttonSave->Enable(enable);
00550     buttonSaveAs->Enable(enable);
00551     buttonAssignInput->Enable(enable);
00552     buttonAssignOutput->Enable(enable);
00553     listTables->Enable(enable);
00554     listRules->Enable(enable);
00555     listFPs->Enable(enable);
00556     listInputs->Enable(enable);
00557     listOutputs->Enable(enable);
00558     
00559     if (enable)
00560     {
00561         canvas->SetCursor(*wxSTANDARD_CURSOR);
00562         canvas->setVisible(true, true, true, true, true);
00563     }
00564     else
00565     {
00566         canvas->SetCursor(*wxCROSS_CURSOR);
00567     }
00568 }
00569 
00570 
00572 
00575 void LayoutView::OnKeyPressed(wxKeyEvent &event)
00576 {
00577     //The escape key is used to escape the assigning mode
00578     if (event.GetKeyCode() == WXK_ESCAPE)
00579     {
00580         controller->escapePressed();
00581     }
00582 }
00583 
00584 
00586 
00589 void LayoutView::OnInputSelected(wxCommandEvent &event)
00590 {
00591     if (event.IsSelection())
00592     {
00593         unsigned long int temp;
00594         event.GetString().Mid(6).ToULong(&temp);
00595        controller->inputSelected(temp - 1);
00596     }
00597 }
00598 
00599 
00601 
00604 void LayoutView::OnOutputSelected(wxCommandEvent &event)
00605 {
00606     if (event.IsSelection())
00607     {
00608        unsigned long int temp;
00609         event.GetString().Mid(7).ToULong(&temp);
00610        controller->outputSelected(temp - 1);
00611     }
00612 }
00613 
00614 
00616 void LayoutView::updateCanvas()
00617 {
00618     canvas->drawScene();
00619 }
00620 
00621 
00623 
00626 void LayoutView::updateInputs(vector<coordinate> inputs)
00627 {
00628     canvas->setAssignedInputs(inputs);
00629 }
00630 
00631 
00633 
00636 void LayoutView::updateOutputs(vector<coordinate> outputs)
00637 {
00638     canvas->setAssignedOutputs(outputs);
00639 }
00640 
00641 
00643 
00646 void LayoutView::OnRuleChecked(wxCommandEvent &event)
00647 {
00648     unsigned long int temp;
00649     wxString selection = listRules->GetString(event.GetSelection());
00650     selection.Mid(4).ToULong(&temp);
00651    controller->ruleChecked(temp, listRules->IsChecked(event.GetSelection()));
00652 }
00653 
00654 
00656 
00659 void LayoutView::OnFPChecked(wxCommandEvent &event)
00660 {
00661    unsigned long int temp;
00662     wxString selection = listFPs->GetString(event.GetSelection());
00663     selection.Mid(8).ToULong(&temp);
00664    controller->FPChecked(temp, listFPs->IsChecked(event.GetSelection()));
00665 }
00666 
00667 
00669 
00674 void LayoutView::checkTable(wxString table, bool enabled)
00675 {
00676     listTables->Check(listTables->FindString(table), enabled);
00677 }
00678 
00679 
00681 
00686 void LayoutView::checkRule(wxString rule, bool enabled)
00687 {
00688     listRules->Check(listRules->FindString(rule), enabled);
00689 }
00690 
00691 
00693 
00698 void LayoutView::checkFP(wxString FP, bool enabled)
00699 {
00700     listFPs->Check(listFPs->FindString(FP), enabled);
00701 }
00702 
00703 
00705 
00708 void LayoutView::OnPrepare(wxCommandEvent &event)
00709 {
00710     controller->prepareSimulation();
00711 }
00712 
00713 
00715 
00718 void LayoutView::OnStart(wxCommandEvent &event)
00719 {
00720     controller->startSimulation();
00721 }
00722 
00723 
00725 
00729 void LayoutView::enableCheckSimulation(bool enable)
00730 {
00731     buttonPrepareSimulation->Enable(enable);
00732 }
00733 
00734 
00736 
00740 void LayoutView::enableStartSimulation(bool enable)
00741 {
00742     buttonStartSimulation->Enable(enable);
00743 }

Generated on Fri Sep 1 23:55:14 2006 for NanoComp by  doxygen 1.4.6