ImagesTree.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00010 /*  This program is free software; you can redistribute it and/or
00011  *  modify it under the terms of the GNU General Public
00012  *  License as published by the Free Software Foundation; either
00013  *  version 2 of the License, or (at your option) any later version.
00014  *
00015  *  This software is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  *  General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public
00021  *  License along with this software. If not, see
00022  *  <http://www.gnu.org/licenses/>.
00023  *
00024  */
00025 
00026 #include "hugin_config.h"
00027 #include "panoinc_WX.h"
00028 #include "panoinc.h"
00029 
00030 #include "base_wx/wxPlatform.h"
00031 #include "base_wx/LensTools.h"
00032 #include "hugin/ImagesTree.h"
00033 #include "base_wx/wxImageCache.h"
00034 #include "base_wx/platform.h"
00035 #include "hugin_base/algorithms/basic/LayerStacks.h"
00036 #include <panodata/ImageVariableGroup.h>
00037 #include <panodata/StandardImageVariableGroups.h>
00038 #include "base_wx/CommandHistory.h"
00039 #include "base_wx/PanoCommand.h"
00040 #include <hugin_utils/stl_utils.h>
00041 #include "hugin/ImageVariableDialog.h"
00042 #include "hugin/huginApp.h"
00043 #include "hugin/MainFrame.h"
00044 #include "hugin/GLPreviewFrame.h"
00045 #include <wx/renderer.h>
00046 
00047 enum
00048 {
00049     ID_LINK=wxID_HIGHEST+230,
00050     ID_UNLINK,
00051     ID_EDIT,
00052     ID_SELECT_ALL,
00053     ID_UNSELECT_ALL,
00054     ID_SELECT_LENS_STACK,
00055     ID_UNSELECT_LENS_STACK,
00056     ID_OPERATION_START=wxID_HIGHEST+300
00057 };
00058 
00059 BEGIN_EVENT_TABLE(ImagesTreeCtrl, wxTreeListCtrl)
00060     EVT_LIST_COL_END_DRAG(-1, ImagesTreeCtrl::OnColumnWidthChange)
00061     EVT_TREE_ITEM_MENU(-1, ImagesTreeCtrl::OnContextMenu)
00062     EVT_LIST_COL_RIGHT_CLICK(-1, ImagesTreeCtrl::OnHeaderContextMenu)
00063     EVT_MENU(ID_LINK, ImagesTreeCtrl::OnLinkImageVariables)
00064     EVT_MENU(ID_UNLINK, ImagesTreeCtrl::OnUnlinkImageVariables)
00065     EVT_MENU(ID_EDIT, ImagesTreeCtrl::OnEditImageVariables)
00066     EVT_MENU(ID_SELECT_ALL, ImagesTreeCtrl::OnSelectAll)
00067     EVT_MENU(ID_UNSELECT_ALL, ImagesTreeCtrl::OnUnselectAll)
00068     EVT_MENU(ID_SELECT_LENS_STACK, ImagesTreeCtrl::OnSelectLensStack)
00069     EVT_MENU(ID_UNSELECT_LENS_STACK, ImagesTreeCtrl::OnUnselectLensStack)
00070     EVT_MENU_RANGE(ID_OPERATION_START, ID_OPERATION_START+50, ImagesTreeCtrl::OnExecuteOperation)
00071     EVT_TREE_BEGIN_DRAG(-1, ImagesTreeCtrl::OnBeginDrag)
00072     EVT_LEFT_UP(ImagesTreeCtrl::OnLeftUp)
00073     EVT_LEFT_DCLICK(ImagesTreeCtrl::OnLeftDblClick)
00074     EVT_TREE_KEY_DOWN(-1, ImagesTreeCtrl::OnChar)
00075     EVT_TREE_BEGIN_LABEL_EDIT(-1, ImagesTreeCtrl::OnBeginEdit)
00076     EVT_TREE_END_LABEL_EDIT(-1, ImagesTreeCtrl::OnEndEdit)
00077 END_EVENT_TABLE()
00078 
00079 class ImagesTreeData : public wxTreeItemData
00080 {
00081 public:
00082     explicit ImagesTreeData(const long& nr) : m_nr(nr) { };
00083     const long GetImgNr() const { return m_nr;};
00084     void SetImgNr(long newImgNr) { m_nr=newImgNr;};
00085     const long GetGroupNr() const { return -(m_nr+1);};
00086     const bool IsGroup() const { return (m_nr<0); };
00087 
00088 private:
00089     long m_nr;
00090 };
00091 
00092 // Define a constructor for the Images Panel
00093 ImagesTreeCtrl::ImagesTreeCtrl()
00094 {
00095     m_pano = NULL;
00096     m_groupMode=GROUP_NONE;
00097     m_guiLevel=GUI_SIMPLE;
00098     m_dragging=false;
00099     m_displayMode=DISPLAY_GENERAL;
00100     m_optimizerMode=false;
00101     m_needsUpdate=true;
00102 }
00103 
00104 bool ImagesTreeCtrl::Create(wxWindow* parent, wxWindowID id,
00105                         const wxPoint& pos,
00106                         const wxSize& size,
00107                         long style,
00108                         const wxString& name)
00109 {
00110     DEBUG_TRACE("List");
00111     if (! wxTreeListCtrl::Create(parent, id, pos, size, style | wxTR_DEFAULT_STYLE|wxTR_HIDE_ROOT|wxTR_NO_LINES|wxTR_FULL_ROW_HIGHLIGHT|wxTR_ROW_LINES|wxTR_LINES_AT_ROOT|wxTR_MULTIPLE) )
00112     {
00113         return false;
00114     }
00115 
00116     DEBUG_TRACE("Tree, adding columns");
00117     m_configClassName = wxT("/ImagesTree");
00118     CreateColumns();
00119     DEBUG_TRACE("");
00120     m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigits"),1);
00121     m_pixelDigits = wxConfigBase::Get()->Read(wxT("/General/PixelFractionalDigits"),1);
00122     m_distDigits = wxConfigBase::Get()->Read(wxT("/General/DistortionFractionalDigits"),3);
00123     //create root
00124     m_root=AddRoot(wxT("root"));
00125     return true;
00126 }
00127 
00128 void ImagesTreeCtrl::CreateColumns()
00129 {
00130     size_t counter=0;
00131 #define ADDCOLUMN(header, mapName, width, align, isEditable, IVE, tooltip) \
00132     AddColumn(header, width, align, -1, true, false, tooltip);\
00133     m_columnMap[mapName]=counter;\
00134     m_columnVector.push_back(mapName);\
00135     if(isEditable)\
00136     {\
00137         m_editableColumns.insert(counter);\
00138     };\
00139     m_variableVector.push_back(IVE);\
00140     counter++;
00141     ADDCOLUMN(wxT("#"), "imgNr", 35, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image number"))
00142     ADDCOLUMN(_("Filename"), "filename", 200, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Filename"))
00143     ADDCOLUMN(_("Width"), "width", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image width"))
00144     ADDCOLUMN(_("Height"), "height", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image height"))
00145     ADDCOLUMN(_("Anchor"), "anchor", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Anchor image for position and/or exposure"))
00146     ADDCOLUMN(_("# Ctrl Pnts"), "cps", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Number of control points in this image"))
00147     ADDCOLUMN(_("Lens no."), "lensNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned lens number"))
00148     ADDCOLUMN(_("Stack no."), "stackNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned stack number"))
00149 
00150     ADDCOLUMN(_("Maker"), "maker", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera maker"))
00151     ADDCOLUMN(_("Model"), "model", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera model"))
00152     ADDCOLUMN(_("Lens"), "lens", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Used lens"))
00153     ADDCOLUMN(_("Capture date"), "date", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Date, image was taken"))
00154     ADDCOLUMN(_("Focal length"), "focallength", 80, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Focal length"))
00155     ADDCOLUMN(_("Aperture"), "aperture", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Aperture"))
00156     ADDCOLUMN(_("Shutter Speed"), "time", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Shutter speed"))
00157     ADDCOLUMN(_("ISO"), "iso", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("ISO speed"))
00158 
00159     ADDCOLUMN(_("Yaw (y)"), "y", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Yaw"))
00160     ADDCOLUMN(_("Pitch (p)"), "p", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Pitch"))
00161     ADDCOLUMN(_("Roll (r)"), "r", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Roll"))
00162     ADDCOLUMN(wxT("X (TrX)"), "TrX", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation X"))
00163     ADDCOLUMN(wxT("Y (TrY)"), "TrY", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Y"))
00164     ADDCOLUMN(wxT("Z (TrZ)"), "TrZ", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Z"))
00165     ADDCOLUMN(_("Plane yaw"), "Tpy", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane yaw"))
00166     ADDCOLUMN(_("Plane pitch"), "Tpp", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane pitch"))
00167     ADDCOLUMN(_("Camera translation"), "cam_trans", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation"))
00168 
00169     ADDCOLUMN(_("Lens type (f)"), "projection", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Lens type (rectilinear, fisheye, equirectangular, ...)"))
00170     ADDCOLUMN(_("Hfov (v)"), "v", 80, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_HFOV, _("Horizontal field of view (v)"))
00171     ADDCOLUMN(wxT("a"), "a", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (a)"))
00172     ADDCOLUMN(wxT("b"), "b", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (b, barrel)"))
00173     ADDCOLUMN(wxT("c"), "c", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (c)"))
00174     ADDCOLUMN(wxT("d"), "d", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Horizontal image center shift (d)"))
00175     ADDCOLUMN(wxT("e"), "e", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Vertical image center shift (e)"))
00176     ADDCOLUMN(wxT("g"), "g", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Horizontal image shearing (g)"))
00177     ADDCOLUMN(wxT("t"), "t", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Vertical image shearing (t)"))
00178 
00179     ADDCOLUMN(wxT("EV"), "Eev", 50, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_ExposureValue, _("Exposure value (Eev)"))
00180     ADDCOLUMN(wxT("Er"), "Er", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceRed, _("Red multiplier (Er)"))
00181     ADDCOLUMN(wxT("Eb"), "Eb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceBlue, _("Blue multiplier (Eb)"))
00182     ADDCOLUMN(wxT("Vb"), "Vb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
00183     ADDCOLUMN(wxT("Vc"), "Vc", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
00184     ADDCOLUMN(wxT("Vd"), "Vd", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
00185     ADDCOLUMN(wxT("Vx"), "Vx", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Horizontal vignetting center shift (Vx)"))
00186     ADDCOLUMN(wxT("Vy"), "Vy", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Vertical vignetting center shift (Vy)"))
00187     ADDCOLUMN(_("Response type"), "response", 80, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera response type"))
00188     ADDCOLUMN(wxT("Ra"), "Ra", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00189     ADDCOLUMN(wxT("Rb"), "Rb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00190     ADDCOLUMN(wxT("Rc"), "Rc", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00191     ADDCOLUMN(wxT("Rd"), "Rd", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00192     ADDCOLUMN(wxT("Re"), "Re", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00193 
00194     //empty column to have enough space on the right side
00195     AddColumn(wxEmptyString,10);
00196 
00197     //get saved width
00198     for ( int j=0; j < GetColumnCount() ; j++ )
00199     {
00200         // -1 is auto
00201         int width = wxConfigBase::Get()->Read(wxString::Format(m_configClassName+wxT("/ColumnWidth%d"), j ), -1);
00202         if(width != -1)
00203             SetColumnWidth(j, width);
00204     }
00205 };
00206 
00207 void ImagesTreeCtrl::Init(HuginBase::Panorama * panorama)
00208 {
00209     m_pano = panorama;
00210     m_pano->addObserver(this);
00211     
00213     m_variable_groups = new HuginBase::StandardImageVariableGroups(*m_pano);
00214     DEBUG_ASSERT(m_variable_groups);
00215     
00216 #ifdef __WXMAC__
00217     SetDropTarget(new PanoDropTarget(*m_pano, true));
00218 #endif
00219 }
00220 
00221 ImagesTreeCtrl::~ImagesTreeCtrl(void)
00222 {
00223     DEBUG_TRACE("");
00224     m_pano->removeObserver(this);
00225     delete m_variable_groups;
00226 };
00227 
00228 void ImagesTreeCtrl::panoramaChanged(HuginBase::Panorama & pano)
00229 {
00230     if(m_optimizerMode)
00231     {
00232         Freeze();
00233         UpdateOptimizerVariables();
00234         Thaw();
00235 #ifdef __WXGTK__
00236         Refresh();
00237 #endif
00238     };
00239     if(m_needsUpdate && (m_groupMode==GROUP_OUTPUTLAYERS || m_groupMode==GROUP_OUTPUTSTACK))
00240     {
00241         HuginBase::UIntSet imgs;
00242         fill_set(imgs, 0, pano.getNrOfImages()-1);
00243         panoramaImagesChanged(pano, imgs);
00244     };
00245     m_needsUpdate=true;
00246 };
00247 
00248 void ImagesTreeCtrl::panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
00249 {
00250     DEBUG_TRACE("");
00251 
00252     Freeze();
00253     HuginBase::UIntSet changedImgs(changed);
00254     // Make sure the part numbers are up to date before writing them to the table.
00255     size_t oldLensCount=m_variable_groups->getLenses().getNumberOfParts();
00256     size_t oldStackCount=m_variable_groups->getStacks().getNumberOfParts();
00257     m_variable_groups->update();
00258     //if the number of lenses or stacks have changed we need to update all images
00259     //because the changed images set contains only the list of the changed imagges
00260     //but not these images where the stack or lens number has changed because
00261     //an images has been inserted
00262     if(pano.getNrOfImages()>0)
00263     {
00264         if(m_variable_groups->getLenses().getNumberOfParts()!=oldLensCount ||
00265             m_variable_groups->getStacks().getNumberOfParts()!=oldStackCount)
00266         {
00267             fill_set(changedImgs, 0, pano.getNrOfImages()-1);
00268         };
00269     };
00270     if(m_optimizerMode)
00271     {
00272         if(m_groupMode==GROUP_NONE && m_pano->getNrOfImages()>m_variable_groups->getStacks().getNumberOfParts())
00273         {
00274             SetGroupMode(GROUP_STACK);
00275         };
00276         if(m_groupMode==GROUP_STACK && m_pano->getNrOfImages()==m_variable_groups->getStacks().getNumberOfParts())
00277         {
00278             SetGroupMode(GROUP_NONE);
00279         };
00280     };
00281     if(m_groupMode==GROUP_NONE)
00282     {
00283         HuginBase::UIntSet imgs;
00284         if(m_pano->getNrOfImages()>0)
00285         {
00286             fill_set(imgs,0,m_pano->getNrOfImages()-1);
00287         };
00288         UpdateGroup(m_root,imgs,changedImgs);
00289     }
00290     else
00291     {
00292         HuginBase::UIntSetVector imageGroups;
00293         switch (m_groupMode)
00294         {
00295             case GROUP_LENS:
00296                 imageGroups = m_variable_groups->getLenses().getPartsSet();
00297                 break;
00298             case GROUP_STACK:
00299                 imageGroups = m_variable_groups->getStacks().getPartsSet();
00300                 break;
00301             case GROUP_OUTPUTSTACK:
00302                 imageGroups=getHDRStacks(*m_pano,m_pano->getActiveImages(), m_pano->getOptions());
00303                 break;
00304             case GROUP_OUTPUTLAYERS:
00305                 imageGroups=getExposureLayers(*m_pano,m_pano->getActiveImages(), m_pano->getOptions());
00306                 break;
00307         };
00308 
00309         size_t nrItems=GetChildrenCount(m_root,false);
00310         if(nrItems!=imageGroups.size())
00311         {
00312             if(nrItems<imageGroups.size())
00313             {
00314                 for(size_t i=nrItems;i<imageGroups.size();i++)
00315                 {
00316                     AppendItem(m_root,wxEmptyString,-1,-1,new ImagesTreeData(-(long)i-1));
00317                 };
00318             }
00319             else
00320             {
00321                 while(GetChildrenCount(m_root,false)>imageGroups.size())
00322                 {
00323                     wxTreeItemIdValue cookie;
00324                     wxTreeItemId item=GetLastChild(m_root,cookie);
00325                     Delete(item);
00326                 };
00327             };
00328         };
00329 
00330         wxTreeItemIdValue cookie;
00331         wxTreeItemId item=GetFirstChild(m_root, cookie);
00332         size_t i=0;
00333         while(item.IsOk())
00334         {
00335             UpdateGroup(item,imageGroups[i++],changedImgs);
00336             UpdateGroupText(item);
00337             item=GetNextChild(m_root, cookie);
00338         };
00339     };
00340     // updates checkboxes images for optimizer variables
00341     if(m_optimizerMode)
00342     {
00343         UpdateOptimizerVariables();
00344     };
00345 
00346     Thaw();
00347     m_needsUpdate = false;
00348 
00349     // HACK! need to notify clients anyway... send dummy event..
00350     // lets hope our clients query for the selected images with GetSelected()
00351     // and do not try to interpret the event.
00352     wxListEvent e;
00353     e.SetEventType(wxEVT_COMMAND_LIST_ITEM_SELECTED);
00354     e.m_itemIndex = -1;
00355     GetEventHandler()->ProcessEvent(e);
00356 }
00357 
00358 void ImagesTreeCtrl::UpdateImageText(wxTreeItemId item)
00359 {
00360     ImagesTreeData* itemData=static_cast<ImagesTreeData*>(GetItemData(item));
00361     // NAMEisLinked returns always false, if the lens or stacks contains only a single image
00362     // so add a special handling for this case
00363     bool isSingleImage = false;
00364     if (m_groupMode != GROUP_NONE)
00365     {
00366         isSingleImage = (GetChildrenCount(GetItemParent(item)) == 1);
00367     };
00368     wxString s;
00369     const size_t imgNr=itemData->GetImgNr();
00370     const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
00371     wxFileName fn(wxString (img.getFilename().c_str(), HUGIN_CONV_FILENAME));
00372 
00373     s << imgNr;
00374     SetItemText(item, m_columnMap["imgNr"], s);
00375     s.Clear();
00376     SetItemText(item, m_columnMap["filename"], fn.GetFullName() );
00377     SetItemText(item, m_columnMap["width"], wxString::Format(wxT("%d"), img.getSize().width()));
00378     SetItemText(item, m_columnMap["height"], wxString::Format(wxT("%d"), img.getSize().height()));
00379 
00380     wxChar flags[] = wxT("--");
00381     if (m_pano->getOptions().optimizeReferenceImage == imgNr)
00382     {
00383         flags[0]='A';
00384     }
00385     if (m_pano->getOptions().colorReferenceImage == imgNr)
00386     {
00387         flags[1]='C';
00388     }
00389     SetItemText(item, m_columnMap["anchor"], wxString(flags, wxConvLocal));
00390     std::vector<unsigned int> cps = m_pano->getCtrlPointsForImage(imgNr);
00391     s << cps.size();
00392     SetItemText(item, m_columnMap["cps"], s);
00393     s.Clear();
00394     const unsigned int stackNumber = m_variable_groups->getStacks().getPartNumber(imgNr);
00395     SetItemText(item, m_columnMap["stackNr"], wxString::Format(wxT("%u"), stackNumber));
00396     const unsigned int lensNr=m_variable_groups->getLenses().getPartNumber(imgNr);
00397     SetItemText(item, m_columnMap["lensNr"], wxString::Format(wxT("%u"), lensNr));
00398 
00399     SetItemText(item, m_columnMap["maker"], wxString(img.getExifMake().c_str(), wxConvLocal));
00400     SetItemText(item, m_columnMap["model"], wxString(img.getExifModel().c_str(), wxConvLocal));
00401     SetItemText(item, m_columnMap["lens"], wxString(img.getExifLens().c_str(), wxConvLocal));
00402     struct tm exifdatetime;
00403     if(img.getExifDateTime(&exifdatetime)==0)
00404     {
00405         wxDateTime s_datetime=wxDateTime(exifdatetime);
00406         s=s_datetime.Format();
00407     }
00408     else
00409     {
00410         s = wxString(img.getExifDate().c_str(),wxConvLocal);
00411     }
00412     SetItemText(item, m_columnMap["date"], s);
00413 
00414     if(img.getExifFocalLength()>0.0)
00415     {
00416         if(img.getExifFocalLength35()>0.0)
00417         {
00418             s = wxString::Format(wxT("%0.1f mm (%0.0f mm)"),img.getExifFocalLength(),img.getExifFocalLength35());
00419         }
00420         else
00421         {
00422             s = wxString::Format(wxT("%0.1f mm"),img.getExifFocalLength());
00423         };
00424     }
00425     else
00426     {
00427         s = wxEmptyString;
00428     };
00429     SetItemText(item, m_columnMap["focallength"], s);
00430 
00431     if(img.getExifAperture()>0)
00432     {
00433         s=wxString::Format(wxT("F%.1f"),img.getExifAperture());
00434     }
00435     else
00436     {
00437         s=wxEmptyString;
00438     };
00439     SetItemText(item, m_columnMap["aperture"], s);
00440 
00441     if(img.getExifExposureTime()>0.5)
00442     {
00443         if(img.getExifExposureTime()>=1.0) 
00444         {
00445             if(img.getExifExposureTime()>=10.0) 
00446             {
00447                 s=wxString::Format(wxT("%3.0f s"),img.getExifExposureTime());
00448             }
00449             else
00450             {
00451                 s=wxString::Format(wxT("%1.1f s"),img.getExifExposureTime());
00452             }
00453         }
00454         else
00455         {
00456             s=wxString::Format(wxT("%1.2f s"),img.getExifExposureTime());
00457         }
00458     }
00459     else
00460     {
00461         if (img.getExifExposureTime() > 1e-9)
00462         {
00463             s=wxString::Format(wxT("1/%0.0f s"),1.0/img.getExifExposureTime());
00464         } 
00465         else
00466         {
00467             //Sanity
00468             s=wxT("");
00469         }
00470     }
00471     SetItemText(item, m_columnMap["time"], s);
00472 
00473     if(img.getExifISO()>0)
00474     {
00475         s=wxString::Format(wxT("%0.0f"),img.getExifISO());
00476     }
00477     else
00478     {
00479         s=wxEmptyString;
00480     };
00481     SetItemText(item, m_columnMap["iso"], s);
00482 
00483     if (m_groupMode == GROUP_STACK && (img.YawisLinked() || isSingleImage))
00484     {
00485         SetItemText(item, m_columnMap["y"], wxEmptyString);
00486         SetItemText(item, m_columnMap["p"], wxEmptyString);
00487         SetItemText(item, m_columnMap["r"], wxEmptyString);
00488         SetItemText(item, m_columnMap["TrX"], wxEmptyString);
00489         SetItemText(item, m_columnMap["TrY"], wxEmptyString);
00490         SetItemText(item, m_columnMap["TrZ"], wxEmptyString);
00491         SetItemText(item, m_columnMap["Tpy"], wxEmptyString);
00492         SetItemText(item, m_columnMap["Tpp"], wxEmptyString);
00493         SetItemText(item, m_columnMap["cam_trans"], wxEmptyString);
00494     }
00495     else
00496     {
00497         SetItemText(item, m_columnMap["y"], hugin_utils::doubleTowxString(img.getYaw(), m_degDigits));
00498         SetItemText(item, m_columnMap["p"], hugin_utils::doubleTowxString(img.getPitch(), m_degDigits));
00499         SetItemText(item, m_columnMap["r"], hugin_utils::doubleTowxString(img.getRoll(), m_degDigits));
00500         SetItemText(item, m_columnMap["TrX"], hugin_utils::doubleTowxString(img.getX(), m_degDigits));
00501         SetItemText(item, m_columnMap["TrY"], hugin_utils::doubleTowxString(img.getY(), m_degDigits));
00502         SetItemText(item, m_columnMap["TrZ"], hugin_utils::doubleTowxString(img.getZ(), m_degDigits));
00503         SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
00504         SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
00505         wxString text=_("not active");
00506         if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
00507         {
00508             text=_("active");
00509         };
00510         text.Prepend(wxT(" "));
00511         SetItemText(item, m_columnMap["cam_trans"], text);
00512     };
00513 
00514     if(m_groupMode==GROUP_LENS)
00515     {
00516         SetItemText(item, m_columnMap["projection"], wxEmptyString);
00517         SetItemText(item, m_columnMap["response"], wxEmptyString);
00518     }
00519     else
00520     {
00521         SetItemText(item, m_columnMap["projection"], getProjectionString(img));
00522         SetItemText(item, m_columnMap["response"], getResponseString(img));
00523     };
00524 
00525     if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || isSingleImage))
00526     {
00527         SetItemText(item, m_columnMap["v"], wxEmptyString);
00528     }
00529     else
00530     {
00531         SetItemText(item, m_columnMap["v"], hugin_utils::doubleTowxString(img.getHFOV(), m_degDigits));
00532     };
00533 
00534     if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || isSingleImage))
00535     {
00536         SetItemText(item, m_columnMap["a"], wxEmptyString);
00537         SetItemText(item, m_columnMap["b"], wxEmptyString);
00538         SetItemText(item, m_columnMap["c"], wxEmptyString);
00539     }
00540     else
00541     {
00542         std::vector<double> dist=img.getRadialDistortion();
00543         SetItemText(item, m_columnMap["a"], hugin_utils::doubleTowxString(dist[0],m_distDigits));
00544         SetItemText(item, m_columnMap["b"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00545         SetItemText(item, m_columnMap["c"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00546     };
00547 
00548     if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || isSingleImage))
00549     {
00550         SetItemText(item, m_columnMap["d"], wxEmptyString);
00551         SetItemText(item, m_columnMap["e"], wxEmptyString);
00552     }
00553     else
00554     {
00555         hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
00556         SetItemText(item, m_columnMap["d"], hugin_utils::doubleTowxString(p.x,m_pixelDigits));
00557         SetItemText(item, m_columnMap["e"], hugin_utils::doubleTowxString(p.y,m_pixelDigits));
00558     };
00559 
00560     if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || isSingleImage))
00561     {
00562         SetItemText(item, m_columnMap["g"], wxEmptyString);
00563         SetItemText(item, m_columnMap["t"], wxEmptyString);
00564     }
00565     else
00566     {
00567         hugin_utils::FDiff2D p=img.getShear();
00568         SetItemText(item, m_columnMap["g"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00569         SetItemText(item, m_columnMap["t"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00570     };
00571 
00572     if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || isSingleImage))
00573     {
00574         SetItemText(item, m_columnMap["Eev"], wxEmptyString);
00575     }
00576     else
00577     {
00578         SetItemText(item, m_columnMap["Eev"], hugin_utils::doubleTowxString(img.getExposureValue(), m_pixelDigits));
00579     };
00580 
00581     if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || isSingleImage))
00582     {
00583         SetItemText(item, m_columnMap["Er"], wxEmptyString);
00584     }
00585     else
00586     {
00587         SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
00588     };
00589 
00590     if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || isSingleImage))
00591     {
00592         SetItemText(item, m_columnMap["Eb"], wxEmptyString);
00593     }
00594     else
00595     {
00596         SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
00597     };
00598 
00599     if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || isSingleImage))
00600     {
00601         SetItemText(item, m_columnMap["Vb"], wxEmptyString);
00602         SetItemText(item, m_columnMap["Vc"], wxEmptyString);
00603         SetItemText(item, m_columnMap["Vd"], wxEmptyString);
00604     }
00605     else
00606     {
00607         std::vector<double> dist=img.getRadialVigCorrCoeff();
00608         SetItemText(item, m_columnMap["Vb"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00609         SetItemText(item, m_columnMap["Vc"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00610         SetItemText(item, m_columnMap["Vd"], hugin_utils::doubleTowxString(dist[3],m_distDigits));
00611     };
00612 
00613     if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || isSingleImage))
00614     {
00615         SetItemText(item, m_columnMap["Vx"], wxEmptyString);
00616         SetItemText(item, m_columnMap["Vy"], wxEmptyString);
00617     }
00618     else
00619     {
00620         hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
00621         SetItemText(item, m_columnMap["Vx"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00622         SetItemText(item, m_columnMap["Vy"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00623     };
00624 
00625     if (m_groupMode == GROUP_LENS && (img.EMoRParamsisLinked() || isSingleImage))
00626     {
00627         SetItemText(item, m_columnMap["Ra"], wxEmptyString);
00628         SetItemText(item, m_columnMap["Rb"], wxEmptyString);
00629         SetItemText(item, m_columnMap["Rc"], wxEmptyString);
00630         SetItemText(item, m_columnMap["Rd"], wxEmptyString);
00631         SetItemText(item, m_columnMap["Re"], wxEmptyString);
00632     }
00633     else
00634     {
00635         std::vector<float> vec=img.getEMoRParams();
00636         SetItemText(item, m_columnMap["Ra"], hugin_utils::doubleTowxString(vec[0],m_distDigits));
00637         SetItemText(item, m_columnMap["Rb"], hugin_utils::doubleTowxString(vec[1],m_distDigits));
00638         SetItemText(item, m_columnMap["Rc"], hugin_utils::doubleTowxString(vec[2],m_distDigits));
00639         SetItemText(item, m_columnMap["Rd"], hugin_utils::doubleTowxString(vec[3],m_distDigits));
00640         SetItemText(item, m_columnMap["Re"], hugin_utils::doubleTowxString(vec[4],m_distDigits));
00641     };
00642 };
00643 
00644 void ImagesTreeCtrl::UpdateGroupText(wxTreeItemId item)
00645 {
00646     ImagesTreeData* itemData=static_cast<ImagesTreeData*>(GetItemData(item));
00647     switch(m_groupMode)
00648     {
00649         case GROUP_LENS:
00650             SetItemText(item, 1, wxString::Format(_("Lens %ld"),itemData->GetGroupNr()));
00651             break;
00652         case GROUP_STACK:
00653             SetItemText(item, 1, wxString::Format(_("Stack %ld"),itemData->GetGroupNr()));
00654             break;
00655         case GROUP_OUTPUTSTACK:
00656             SetItemText(item, 1, wxString::Format(_("Output stack %ld"),itemData->GetGroupNr()));
00657             break;
00658         case GROUP_OUTPUTLAYERS:
00659             SetItemText(item, 1, wxString::Format(_("Output exposure layer %ld"),itemData->GetGroupNr()));
00660             break;
00661     };
00662     SetItemBold(item,1,true);
00663     wxTreeItemIdValue cookie;
00664     wxTreeItemId childItem=GetFirstChild(item,cookie);
00665     // NAMEisLinked returns always false, if the lens or stacks contains only a single image
00666     // so add a special handling for this case
00667     bool haveSingleChild = false;
00668     if (m_groupMode != GROUP_NONE)
00669     {
00670         haveSingleChild = (GetChildrenCount(item, false) == 1);
00671     };
00672     if(childItem.IsOk())
00673     {
00674         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(childItem));
00675         const HuginBase::SrcPanoImage& img=m_pano->getImage(data->GetImgNr());
00676 
00677         if (m_groupMode == GROUP_STACK && (img.YawisLinked() || haveSingleChild))
00678         {
00679             SetItemText(item, m_columnMap["y"], hugin_utils::doubleTowxString(img.getYaw(), m_degDigits));
00680             SetItemText(item, m_columnMap["p"], hugin_utils::doubleTowxString(img.getPitch(), m_degDigits));
00681             SetItemText(item, m_columnMap["r"], hugin_utils::doubleTowxString(img.getRoll(), m_degDigits));
00682             SetItemText(item, m_columnMap["TrX"], hugin_utils::doubleTowxString(img.getX(), m_degDigits));
00683             SetItemText(item, m_columnMap["TrY"], hugin_utils::doubleTowxString(img.getY(), m_degDigits));
00684             SetItemText(item, m_columnMap["TrZ"], hugin_utils::doubleTowxString(img.getZ(), m_degDigits));
00685             SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
00686             SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
00687             wxString text=_("not active");
00688             if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
00689             {
00690                 text=_("active");
00691             };
00692             text.Prepend(wxT(" "));
00693             SetItemText(item, m_columnMap["cam_trans"], text);
00694         }
00695         else
00696         {
00697             SetItemText(item, m_columnMap["y"], wxEmptyString);
00698             SetItemText(item, m_columnMap["p"], wxEmptyString);
00699             SetItemText(item, m_columnMap["r"], wxEmptyString);
00700             SetItemText(item, m_columnMap["TrX"], wxEmptyString);
00701             SetItemText(item, m_columnMap["TrY"], wxEmptyString);
00702             SetItemText(item, m_columnMap["TrZ"], wxEmptyString);
00703             SetItemText(item, m_columnMap["Tpy"], wxEmptyString);
00704             SetItemText(item, m_columnMap["Tpp"], wxEmptyString);
00705             SetItemText(item, m_columnMap["cam_trans"], wxEmptyString);
00706         };
00707 
00708         if(m_groupMode==GROUP_LENS)
00709         {
00710             SetItemText(item, m_columnMap["projection"], getProjectionString(img));
00711             SetItemText(item, m_columnMap["response"], getResponseString(img));
00712         }
00713         else
00714         {
00715             SetItemText(item, m_columnMap["projection"], wxEmptyString);
00716             SetItemText(item, m_columnMap["response"], wxEmptyString);
00717         };
00718 
00719         if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || haveSingleChild))
00720         {
00721             SetItemText(item, m_columnMap["v"], hugin_utils::doubleTowxString(img.getHFOV(), m_degDigits));
00722         }
00723         else
00724         {
00725             SetItemText(item, m_columnMap["v"], wxEmptyString);
00726         };
00727 
00728         if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || haveSingleChild))
00729         {
00730             std::vector<double> dist=img.getRadialDistortion();
00731             SetItemText(item, m_columnMap["a"], hugin_utils::doubleTowxString(dist[0],m_distDigits));
00732             SetItemText(item, m_columnMap["b"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00733             SetItemText(item, m_columnMap["c"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00734         }
00735         else
00736         {
00737             SetItemText(item, m_columnMap["a"], wxEmptyString);
00738             SetItemText(item, m_columnMap["b"], wxEmptyString);
00739             SetItemText(item, m_columnMap["c"], wxEmptyString);
00740         };
00741 
00742         if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || haveSingleChild))
00743         {
00744             hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
00745             SetItemText(item, m_columnMap["d"], hugin_utils::doubleTowxString(p.x,m_pixelDigits));
00746             SetItemText(item, m_columnMap["e"], hugin_utils::doubleTowxString(p.y,m_pixelDigits));
00747         }
00748         else
00749         {
00750             SetItemText(item, m_columnMap["d"], wxEmptyString);
00751             SetItemText(item, m_columnMap["e"], wxEmptyString);
00752         };
00753 
00754         if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || haveSingleChild))
00755         {
00756             hugin_utils::FDiff2D p=img.getShear();
00757             SetItemText(item, m_columnMap["g"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00758             SetItemText(item, m_columnMap["t"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00759         }
00760         else
00761         {
00762             SetItemText(item, m_columnMap["g"], wxEmptyString);
00763             SetItemText(item, m_columnMap["t"], wxEmptyString);
00764         };
00765 
00766         if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || haveSingleChild))
00767         {
00768             SetItemText(item, m_columnMap["Eev"], hugin_utils::doubleTowxString(img.getExposureValue(), m_pixelDigits));
00769         }
00770         else
00771         {
00772             SetItemText(item, m_columnMap["Eev"], wxEmptyString);
00773         };
00774 
00775         if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || haveSingleChild))
00776         {
00777             SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
00778         }
00779         else
00780         {
00781             SetItemText(item, m_columnMap["Er"], wxEmptyString);
00782         };
00783 
00784         if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || haveSingleChild))
00785         {
00786             SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
00787         }
00788         else
00789         {
00790             SetItemText(item, m_columnMap["Eb"], wxEmptyString);
00791         };
00792 
00793         if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || haveSingleChild))
00794         {
00795             std::vector<double> dist=img.getRadialVigCorrCoeff();
00796             SetItemText(item, m_columnMap["Vb"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00797             SetItemText(item, m_columnMap["Vc"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00798             SetItemText(item, m_columnMap["Vd"], hugin_utils::doubleTowxString(dist[3],m_distDigits));
00799         }
00800         else
00801         {
00802             SetItemText(item, m_columnMap["Vb"], wxEmptyString);
00803             SetItemText(item, m_columnMap["Vc"], wxEmptyString);
00804             SetItemText(item, m_columnMap["Vd"], wxEmptyString);
00805         };
00806 
00807         if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || haveSingleChild))
00808         {
00809             hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
00810             SetItemText(item, m_columnMap["Vx"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00811             SetItemText(item, m_columnMap["Vy"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00812         }
00813         else
00814         {
00815             SetItemText(item, m_columnMap["Vx"], wxEmptyString);
00816             SetItemText(item, m_columnMap["Vy"], wxEmptyString);
00817         };
00818 
00819         if (m_groupMode == GROUP_LENS && (img.EMoRParamsisLinked() || haveSingleChild))
00820         {
00821             std::vector<float> vec=img.getEMoRParams();
00822             SetItemText(item, m_columnMap["Ra"], hugin_utils::doubleTowxString(vec[0],m_distDigits));
00823             SetItemText(item, m_columnMap["Rb"], hugin_utils::doubleTowxString(vec[1],m_distDigits));
00824             SetItemText(item, m_columnMap["Rc"], hugin_utils::doubleTowxString(vec[2],m_distDigits));
00825             SetItemText(item, m_columnMap["Rd"], hugin_utils::doubleTowxString(vec[3],m_distDigits));
00826             SetItemText(item, m_columnMap["Re"], hugin_utils::doubleTowxString(vec[4],m_distDigits));
00827         }
00828         else
00829         {
00830             SetItemText(item, m_columnMap["Ra"], wxEmptyString);
00831             SetItemText(item, m_columnMap["Rb"], wxEmptyString);
00832             SetItemText(item, m_columnMap["Rc"], wxEmptyString);
00833             SetItemText(item, m_columnMap["Rd"], wxEmptyString);
00834             SetItemText(item, m_columnMap["Re"], wxEmptyString);
00835         };
00836     };
00837 };
00838 
00839 void ImagesTreeCtrl::UpdateGroup(wxTreeItemId parent, const HuginBase::UIntSet imgs, HuginBase::UIntSet& changed)
00840 {
00841     size_t nrItems=GetChildrenCount(parent,false);
00842     bool forceUpdate=false;
00843     if(nrItems!=imgs.size())
00844     {
00845         forceUpdate=true;
00846         if(nrItems<imgs.size())
00847         {
00848             for(size_t i=nrItems;i<imgs.size();i++)
00849             {
00850                 AppendItem(parent,wxEmptyString,-1,-1,new ImagesTreeData(-1));
00851             };
00852         }
00853         else
00854         {
00855             while(GetChildrenCount(parent,false)>imgs.size())
00856             {
00857                 wxTreeItemIdValue cookie;
00858                 wxTreeItemId item=GetLastChild(parent,cookie);
00859                 Delete(item);
00860             };
00861         };
00862     };
00863     //now update values
00864     wxTreeItemIdValue cookie;
00865     wxTreeItemId item=GetFirstChild(parent,cookie);
00866     HuginBase::UIntSet::const_iterator it=imgs.begin();
00867     while(item.IsOk())
00868     {
00869         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
00870         if(it==imgs.end())
00871         {
00872             break;
00873         };
00874         bool needsUpdate=false;
00875         if(data->GetImgNr()!=*it)
00876         {
00877             data->SetImgNr(*it);
00878             needsUpdate=true;
00879         }
00880         else
00881         {
00882             if(set_contains(changed,*it))
00883             {
00884                 needsUpdate=true;
00885             };
00886         };
00887         if(needsUpdate || forceUpdate)
00888         {
00889             UpdateImageText(item);
00890             changed.erase(*it);
00891         };
00892         item=GetNextChild(parent, cookie);
00893         ++it;
00894     };
00895 };
00896 
00897 void ImagesTreeCtrl::UpdateOptimizerVariables()
00898 {
00899     HuginBase::OptimizeVector optVec=m_pano->getOptimizeVector();
00900     wxTreeItemIdValue cookie;
00901     wxTreeItemId item=GetFirstChild(m_root, cookie);
00902     while(item.IsOk())
00903     {
00904         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
00905         HuginBase::UIntSet imgNrs;
00906         if(data->IsGroup())
00907         {
00908             wxTreeItemIdValue childCookie;
00909             wxTreeItemId child=GetFirstChild(item, childCookie);
00910             while(child.IsOk())
00911             {
00912                 data=static_cast<ImagesTreeData*>(GetItemData(child));
00913                 imgNrs.insert(data->GetImgNr());
00914                 child=GetNextChild(item, childCookie);
00915             };
00916         }
00917         else
00918         {
00919             imgNrs.insert(data->GetImgNr());
00920         };
00921         if(imgNrs.size()>0)
00922         {
00923             for(size_t i=0;i<GetColumnCount();i++)
00924             {
00925                 if(set_contains(m_editableColumns,i))
00926                 {
00927                     if (GetItemText(item, i).IsEmpty())
00928                     {
00929                         // item with no text can have no checkbox
00930                         // this can happen with linked variables
00931                         SetItemImage(item, i, -1);
00932                     }
00933                     else
00934                     {
00935                         bool opt=false;
00936                         for(HuginBase::UIntSet::const_iterator it=imgNrs.begin(); it!=imgNrs.end() && !opt;++it)
00937                         {
00938                             if(m_columnVector[i]=="cam_trans")
00939                             {
00940                                 opt=set_contains(optVec[*it], "TrX") &&
00941                                     set_contains(optVec[*it], "TrY") &&
00942                                     set_contains(optVec[*it], "TrZ") &&
00943                                     set_contains(optVec[*it], "Tpy") &&
00944                                     set_contains(optVec[*it], "Tpp");
00945                             }
00946                             else
00947                             {
00948                                 opt=set_contains(optVec[*it], m_columnVector[i]);
00949                             };
00950                         };
00951                         SetItemImage(item, i, opt ? 1 : 0);
00952                     };
00953                 };
00954             };
00955         };
00956         item=GetNext(item);
00957     };
00958 };
00959 
00960 HuginBase::UIntSet ImagesTreeCtrl::GetSelectedImages()
00961 {
00962     wxArrayTreeItemIds selected;
00963     HuginBase::UIntSet imgs;
00964     if(GetSelections (selected)>0)
00965     {
00966         for(size_t i=0;i<selected.size();i++)
00967         {
00968             ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(selected[i]));
00969             if(data->IsGroup())
00970             {
00971                 wxTreeItemIdValue cookie;
00972                 wxTreeItemId item=GetFirstChild(selected[i],cookie);
00973                 while(item.IsOk())
00974                 {
00975                     data=static_cast<ImagesTreeData*>(GetItemData(item));
00976                     imgs.insert(data->GetImgNr());
00977                     item=GetNextChild(selected[i], cookie);
00978                 };
00979             }
00980             else
00981             {
00982                 imgs.insert(data->GetImgNr());
00983             };
00984         };
00985     }
00986     return imgs;
00987 };
00988 
00989 void ImagesTreeCtrl::OnColumnWidthChange( wxListEvent & e )
00990 {
00991     if(m_configClassName != wxT(""))
00992     {
00993         int colNum = e.GetColumn();
00994         wxConfigBase::Get()->Write( m_configClassName+wxString::Format(wxT("/ColumnWidth%d"),colNum), GetColumnWidth(colNum) );
00995     }
00996 }
00997 
00998 void ImagesTreeCtrl::SetGuiLevel(GuiLevel newSetting)
00999 {
01000     m_guiLevel=newSetting;
01001     //update visible column
01002     SetDisplayMode(m_displayMode);
01003 };
01004 
01005 void ImagesTreeCtrl::SetOptimizerMode()
01006 {
01007     m_optimizerMode=true;
01008     // connnect events with handlers
01009     Bind(wxEVT_MOTION, &ImagesTreeCtrl::OnMouseMove, this);
01010     Bind(wxEVT_LEFT_DOWN, &ImagesTreeCtrl::OnLeftDown, this);
01011     //create bitmaps for different checkboxes state
01012     wxRendererNative& renderer = wxRendererNative::Get();
01013     const wxSize checkBoxSize = renderer.GetCheckBoxSize(this);
01014     wxImageList* checkboxImageList = new wxImageList(checkBoxSize.GetWidth(), checkBoxSize.GetHeight(), true, 0);
01015     wxBitmap checkBoxImage(checkBoxSize, 32);
01016     wxMemoryDC dc(checkBoxImage);
01017     // unchecked checkbox
01018     dc.Clear();
01019     renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize));
01020     dc.SelectObject(wxNullBitmap);
01021     checkboxImageList->Add(checkBoxImage);
01022     // checked checkbox
01023     dc.SelectObject(checkBoxImage);
01024     dc.Clear();
01025     renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CHECKED);
01026     dc.SelectObject(wxNullBitmap);
01027     checkboxImageList->Add(checkBoxImage);
01028     // mouse over unchecked checkbox
01029     dc.SelectObject(checkBoxImage);
01030     dc.Clear();
01031     renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CURRENT);
01032     dc.SelectObject(wxNullBitmap);
01033     checkboxImageList->Add(checkBoxImage);
01034     // mouse over checked checkbox
01035     dc.SelectObject(checkBoxImage);
01036     dc.Clear();
01037     renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CHECKED | wxCONTROL_CURRENT);
01038     dc.SelectObject(wxNullBitmap);
01039     checkboxImageList->Add(checkBoxImage);
01040 
01041     AssignImageList(checkboxImageList);
01042     // activate edit mode
01043     for(HuginBase::UIntSet::const_iterator it=m_editableColumns.begin(); it!=m_editableColumns.end(); ++it)
01044     {
01045         if(m_columnVector[*it]!="cam_trans")
01046         {
01047             SetColumnEditable(*it,true);
01048         };
01049     };
01050 };
01051 
01052 void ImagesTreeCtrl::SetGroupMode(GroupMode newGroup)
01053 {
01054     if(newGroup!=m_groupMode)
01055     {
01056         m_groupMode=newGroup;
01057         if(m_groupMode==GROUP_NONE)
01058         {
01059             SetWindowStyle(GetWindowStyle() | wxTR_NO_LINES);
01060         }
01061         else
01062         {
01063             SetWindowStyle(GetWindowStyle() & ~wxTR_NO_LINES);
01064         };
01065         DeleteChildren(m_root);
01066         HuginBase::UIntSet imgs;
01067         if(m_pano->getNrOfImages()>0)
01068         {
01069             fill_set(imgs,0,m_pano->getNrOfImages()-1);
01070         };
01071         panoramaImagesChanged(*m_pano,imgs);
01072         ExpandAll(m_root);
01073     };
01074 };
01075 
01076 void ImagesTreeCtrl::SetDisplayMode(DisplayMode newMode)
01077 {
01078     m_displayMode=newMode;
01079 
01080     SetColumnShown(m_columnMap["width"], m_displayMode==DISPLAY_GENERAL);
01081     SetColumnShown(m_columnMap["height"], m_displayMode==DISPLAY_GENERAL);
01082     SetColumnShown(m_columnMap["anchor"], m_displayMode==DISPLAY_GENERAL);
01083     SetColumnShown(m_columnMap["cps"], m_displayMode==DISPLAY_GENERAL);
01084     SetColumnShown(m_columnMap["lensNr"], m_displayMode==DISPLAY_GENERAL);
01085     SetColumnShown(m_columnMap["stackNr"], m_displayMode==DISPLAY_GENERAL && m_guiLevel>=GUI_ADVANCED);
01086 
01087     SetColumnShown(m_columnMap["maker"], m_displayMode==DISPLAY_EXIF);
01088     SetColumnShown(m_columnMap["model"], m_displayMode==DISPLAY_EXIF);
01089     SetColumnShown(m_columnMap["lens"], m_displayMode==DISPLAY_EXIF);
01090     SetColumnShown(m_columnMap["date"], m_displayMode==DISPLAY_EXIF);
01091     SetColumnShown(m_columnMap["focallength"], m_displayMode==DISPLAY_EXIF);
01092     SetColumnShown(m_columnMap["aperture"], m_displayMode==DISPLAY_EXIF);
01093     SetColumnShown(m_columnMap["time"], m_displayMode==DISPLAY_EXIF);
01094     SetColumnShown(m_columnMap["iso"], m_displayMode==DISPLAY_EXIF);
01095 
01096     SetColumnShown(m_columnMap["y"], m_displayMode==DISPLAY_POSITION);
01097     SetColumnShown(m_columnMap["p"], m_displayMode==DISPLAY_POSITION);
01098     SetColumnShown(m_columnMap["r"], m_displayMode==DISPLAY_POSITION);
01099     SetColumnShown(m_columnMap["TrX"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01100     SetColumnShown(m_columnMap["TrY"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01101     SetColumnShown(m_columnMap["TrZ"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01102     SetColumnShown(m_columnMap["Tpy"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01103     SetColumnShown(m_columnMap["Tpp"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01104     SetColumnShown(m_columnMap["cam_trans"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01105 
01106     SetColumnShown(m_columnMap["projection"], m_displayMode==DISPLAY_LENS);
01107     SetColumnShown(m_columnMap["v"], m_displayMode==DISPLAY_LENS);
01108     SetColumnShown(m_columnMap["a"], m_displayMode==DISPLAY_LENS);
01109     SetColumnShown(m_columnMap["b"], m_displayMode==DISPLAY_LENS);
01110     SetColumnShown(m_columnMap["c"], m_displayMode==DISPLAY_LENS);
01111     SetColumnShown(m_columnMap["d"], m_displayMode==DISPLAY_LENS);
01112     SetColumnShown(m_columnMap["e"], m_displayMode==DISPLAY_LENS);
01113     SetColumnShown(m_columnMap["g"], m_displayMode==DISPLAY_LENS && m_guiLevel>=GUI_EXPERT);
01114     SetColumnShown(m_columnMap["t"], m_displayMode==DISPLAY_LENS && m_guiLevel>=GUI_EXPERT);
01115 
01116     SetColumnShown(m_columnMap["Eev"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_IMAGES);
01117     SetColumnShown(m_columnMap["Er"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_IMAGES);
01118     SetColumnShown(m_columnMap["Eb"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_IMAGES);
01119     SetColumnShown(m_columnMap["Vb"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01120     SetColumnShown(m_columnMap["Vc"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01121     SetColumnShown(m_columnMap["Vd"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01122     SetColumnShown(m_columnMap["Vx"], (m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES) && m_guiLevel>=GUI_ADVANCED);
01123     SetColumnShown(m_columnMap["Vy"], (m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES) && m_guiLevel>=GUI_ADVANCED);
01124     SetColumnShown(m_columnMap["response"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01125     SetColumnShown(m_columnMap["Ra"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01126     SetColumnShown(m_columnMap["Rb"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01127     SetColumnShown(m_columnMap["Rc"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01128     SetColumnShown(m_columnMap["Rd"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01129     SetColumnShown(m_columnMap["Re"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01130 
01131     Refresh();
01132 };
01133 
01134 void ImagesTreeCtrl::OnContextMenu(wxTreeEvent & e)
01135 {
01136     m_selectedColumn=e.GetInt();
01137     wxMenu menu;
01138     bool allowMenuExtension=true;
01139     if(e.GetItem().IsOk())
01140     {
01141         //click on item
01142         if(set_contains(m_editableColumns,m_selectedColumn))
01143         {
01144             bool emptyText=GetItemText(e.GetItem(),m_selectedColumn).IsEmpty();
01145             ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
01146             if((m_groupMode==GROUP_LENS && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Yaw) ||
01147                (m_groupMode==GROUP_STACK && m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw) )
01148             {
01149                 if(data->IsGroup())
01150                 {
01151                     if(emptyText)
01152                     {
01153                         menu.Append(ID_LINK,_("Link"));
01154                     }
01155                     else
01156                     {
01157                         menu.Append(ID_UNLINK, _("Unlink"));
01158                     };
01159                 }
01160                 else
01161                 {
01162                     if(emptyText)
01163                     {
01164                         menu.Append(ID_UNLINK,_("Unlink"));
01165                     }
01166                     else
01167                     {
01168                         menu.Append(ID_LINK, _("Link"));
01169                     };
01170                 };
01171                 menu.AppendSeparator();
01172             };
01173             if(m_optimizerMode)
01174             {
01175                 if(data->IsGroup() == emptyText)
01176                 {
01177                     if(m_groupMode==GROUP_LENS && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Yaw)
01178                     {
01179                         menu.Append(ID_SELECT_LENS_STACK, _("Select all for current lens"));
01180                         menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current lens"));
01181                     };
01182                     if(m_groupMode==GROUP_STACK && m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
01183                     {
01184                         menu.Append(ID_SELECT_LENS_STACK, _("Select all for current stack"));
01185                         menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current stack"));
01186                     };
01187                 };
01188                 if(m_columnVector[m_selectedColumn]!="cam_trans")
01189                 {
01190                     menu.Append(ID_SELECT_ALL, _("Select all"));
01191                 };
01192                 menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
01193                 menu.AppendSeparator();
01194             }
01195         };
01196         menu.Append(ID_EDIT, _("Edit image variables..."));
01197     }
01198     else
01199     {
01200         if(m_optimizerMode && set_contains(m_editableColumns, e.GetInt()))
01201         {
01202             if(m_columnVector[m_selectedColumn]!="cam_trans")
01203             {
01204                 menu.Append(ID_SELECT_ALL, _("Select all"));
01205             };
01206             menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
01207             allowMenuExtension=false;
01208         }
01209     };
01210     if(allowMenuExtension)
01211     {
01212         if(menu.GetMenuItemCount()>0)
01213         {
01214             menu.AppendSeparator();
01215         };
01216         int id=ID_OPERATION_START;
01217         m_menuOperation.clear();
01218         GenerateSubMenu(&menu, PanoOperation::GetImagesOperationVector(), id);
01219         wxMenu* subMenu=new wxMenu();
01220         GenerateSubMenu(subMenu, PanoOperation::GetLensesOperationVector(), id);
01221         if(subMenu->GetMenuItemCount()>0)
01222         {
01223             menu.Append(-1,_("Lens"), subMenu);
01224         }
01225         else
01226         {
01227             delete subMenu;
01228         };
01229         if(m_guiLevel>GUI_SIMPLE)
01230         {
01231             subMenu=new wxMenu();
01232             GenerateSubMenu(subMenu, PanoOperation::GetStacksOperationVector(), id);
01233             if(subMenu->GetMenuItemCount()>0)
01234             {
01235                 menu.Append(-1,_("Stacks"), subMenu);
01236             }
01237             else
01238             {
01239                 delete subMenu;
01240             };
01241         };
01242         subMenu=new wxMenu();
01243         GenerateSubMenu(subMenu, PanoOperation::GetControlPointsOperationVector(), id);
01244         if(subMenu->GetMenuItemCount()>0)
01245         {
01246             menu.Append(-1, _("Control points"), subMenu);
01247         }
01248         else
01249         {
01250             delete subMenu;
01251         };
01252         subMenu=new wxMenu();
01253         GenerateSubMenu(subMenu, PanoOperation::GetResetOperationVector(), id);
01254         if(subMenu->GetMenuItemCount()>0)
01255         {
01256             menu.Append(-1, _("Reset"), subMenu);
01257         }
01258         else
01259         {
01260             delete subMenu;
01261         };
01262     };
01263     if(menu.GetMenuItemCount()>0)
01264     {
01265         PopupMenu(&menu);
01266     };
01267     e.Skip();
01268 };
01269 
01270 void ImagesTreeCtrl::GenerateSubMenu(wxMenu* menu, PanoOperation::PanoOperationVector* operations, int& id)
01271 {
01272     HuginBase::UIntSet imgs=GetSelectedImages();
01273     for(size_t i=0; i<operations->size(); i++)
01274     {
01275         if((*operations)[i]->IsEnabled(*m_pano, imgs, m_guiLevel))
01276         {
01277             menu->Append(id, (*operations)[i]->GetLabel());
01278             m_menuOperation[id]=(*operations)[i];
01279             id++;
01280         }
01281     };
01282 };
01283 
01284 void ImagesTreeCtrl::OnHeaderContextMenu(wxListEvent & e)
01285 {
01286     m_selectedColumn=e.GetColumn();
01287     wxMenu menu;
01288     if(m_optimizerMode && set_contains(m_editableColumns, m_selectedColumn))
01289     {
01290         menu.Append(ID_SELECT_ALL, _("Select all"));
01291         menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
01292         PopupMenu(&menu);
01293     };
01294     e.Skip();
01295 };
01296 
01297 void ImagesTreeCtrl::UnLinkImageVariables(bool linked)
01298 {
01299     HuginBase::UIntSet images=GetSelectedImages();
01300     if(images.size()>0 && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Filename)
01301     {
01302         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
01303         variables.insert(m_variableVector[m_selectedColumn]);
01304         if(m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
01305         {
01306             variables.insert(HuginBase::ImageVariableGroup::IVE_Pitch);
01307             variables.insert(HuginBase::ImageVariableGroup::IVE_Roll);
01308             variables.insert(HuginBase::ImageVariableGroup::IVE_X);
01309             variables.insert(HuginBase::ImageVariableGroup::IVE_Y);
01310             variables.insert(HuginBase::ImageVariableGroup::IVE_Z);
01311             variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw);
01312             variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch);
01313         };
01314         if(m_groupMode==GROUP_LENS)
01315         {
01316             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01317                 new PanoCommand::ChangePartImagesLinkingCmd(*m_pano, images, variables, linked, HuginBase::StandardImageVariableGroups::getLensVariables())
01318             );
01319         }
01320         else
01321         {
01322             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01323                 new PanoCommand::ChangePartImagesLinkingCmd(*m_pano, images, variables, linked, HuginBase::StandardImageVariableGroups::getStackVariables())
01324             );
01325         };
01326     };
01327 };
01328 
01329 void ImagesTreeCtrl::OnLinkImageVariables(wxCommandEvent &e)
01330 {
01331     UnLinkImageVariables(true);
01332 };
01333 
01334 void ImagesTreeCtrl::OnUnlinkImageVariables(wxCommandEvent &e)
01335 {
01336     UnLinkImageVariables(false);
01337 };
01338 
01339 void ImagesTreeCtrl::OnEditImageVariables(wxCommandEvent &e)
01340 {
01341     HuginBase::UIntSet imgs=GetSelectedImages();
01342     if(imgs.size()>0)
01343     {
01344         ImageVariableDialog dlg(this, m_pano, imgs);
01345         dlg.SetGuiLevel(m_guiLevel);
01346         switch(m_displayMode)
01347         {
01348             case DISPLAY_LENS:
01349                 dlg.SelectTab(1);
01350                 break;
01351             case DISPLAY_PHOTOMETRICS:
01352             case DISPLAY_PHOTOMETRICS_IMAGES:
01353             case DISPLAY_PHOTOMETRICS_LENSES:
01354                 if(m_selectedColumn==m_columnMap["response"] ||
01355                     m_selectedColumn==m_columnMap["Ra"] ||
01356                     m_selectedColumn==m_columnMap["Rb"] ||
01357                     m_selectedColumn==m_columnMap["Rc"] ||
01358                     m_selectedColumn==m_columnMap["Rd"] ||
01359                     m_selectedColumn==m_columnMap["Re"] )
01360                 {
01361                     dlg.SelectTab(3);
01362                 }
01363                 else
01364                 {
01365                     dlg.SelectTab(2);
01366                 };
01367                 break;
01368             default:
01369                 break;
01370         };
01371         dlg.ShowModal();
01372     };
01373 };
01374 
01375 void ImagesTreeCtrl::OnBeginDrag(wxTreeEvent &e)
01376 {
01377     const bool ctrlPressed=wxGetKeyState(WXK_COMMAND);
01378     if(m_pano->getNrOfImages()>0 && !m_dragging)
01379     {
01380         m_draggingImages=GetSelectedImages();
01381         if(m_draggingImages.size()>0)
01382         {
01383             if((m_groupMode==GROUP_NONE && m_draggingImages.size()==1 && !ctrlPressed) ||
01384                 m_groupMode==GROUP_LENS || m_groupMode==GROUP_STACK)
01385             {
01386                 e.Allow();
01387                 SetCursor(wxCURSOR_HAND);
01388                 m_dragging=true;
01389             };
01390         };
01391     };
01392 };
01393 
01394 void ImagesTreeCtrl::OnLeftUp(wxMouseEvent &e)
01395 {
01396     //we can't use wxEVT_TREE_END_DRAG because this event is fire several times, e.g. when
01397     // the mouse leaves the area of the tree
01398     // so we are listing to left mouse up, as described in documentation
01399     if(m_dragging)
01400     {
01401         SetCursor(wxCURSOR_ARROW);
01402         m_dragging=false;
01403         wxTreeItemId item=HitTest(e.GetPosition());
01404         if(m_groupMode==GROUP_NONE)
01405         {
01406             size_t img1=*m_draggingImages.begin();
01407             size_t img2=-1;
01408             if(item.IsOk())
01409             {
01410                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
01411                 img2=data->GetImgNr();
01412             }
01413             else
01414             {
01415                 //we are checking the points above, if we find then
01416                 // an item, the user drop it below the last item, if not
01417                 // the drop happened right beside the item
01418                 wxPoint pos(e.GetPosition());
01419                 pos.y-=10;
01420                 while(pos.y>0)
01421                 {
01422                     item=HitTest(pos);
01423                     if(item.IsOk())
01424                     {
01425                         img2=m_pano->getNrOfImages()-1;
01426                         break;
01427                     };
01428                     pos.y-=10;
01429                 };
01430             };
01431             if(img2!=-1)
01432             {
01433                 if(img1!=img2)
01434                 {
01435                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01436                         new PanoCommand::MoveImageCmd(*m_pano, img1, img2)
01437                     );
01438                     // now update drag images groups in fast preview window, this information is not stored in Panorama class
01439                     HuginBase::UIntSet images = MainFrame::Get()->getGLPreview()->GetDragGroupImages();
01440                     if (!images.empty() && images.size() < m_pano->getNrOfImages())
01441                     {
01442                         std::vector<bool> imgList(m_pano->getNrOfImages(), false);
01443                         for (auto& i : images)
01444                         {
01445                             imgList[i] = true;
01446                         };
01447                         const bool moveImageChecked = imgList[img1];
01448                         imgList.erase(imgList.begin() + img1);
01449                         if (img2 < imgList.size())
01450                         {
01451                             imgList.insert(imgList.begin() + img2, moveImageChecked);
01452                         }
01453                         else
01454                         {
01455                             imgList.push_back(moveImageChecked);
01456                         };
01457                         images.clear();
01458                         for (size_t i = 0; i < imgList.size(); ++i)
01459                         {
01460                             if (imgList[i])
01461                             {
01462                                 images.insert(i);
01463                             };
01464                         };
01465                         MainFrame::Get()->getGLPreview()->SetDragGroupImages(images, true);
01466                     };
01467                 };
01468             };
01469         }
01470         else
01471         {
01472             //dragging to stack/lenses
01473             if(item.IsOk())
01474             {
01475                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
01476                 long groupNr=-1;
01477                 if(data->IsGroup())
01478                 {
01479                     groupNr=data->GetGroupNr();
01480                 }
01481                 else
01482                 {
01483                     item=GetItemParent(item);
01484                     if(item.IsOk())
01485                     {
01486                         data=static_cast<ImagesTreeData*>(GetItemData(item));
01487                         groupNr=data->GetGroupNr();
01488                     };
01489                 };
01490                 if(groupNr>=0)
01491                 {
01492                     if(m_groupMode==GROUP_LENS)
01493                     {
01494                         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01495                             new PanoCommand::ChangePartNumberCmd(*m_pano, m_draggingImages, groupNr, HuginBase::StandardImageVariableGroups::getLensVariables())
01496                         );
01497                     }
01498                     else
01499                     {
01500                         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01501                             new PanoCommand::ChangePartNumberCmd(*m_pano, m_draggingImages, groupNr, HuginBase::StandardImageVariableGroups::getStackVariables())
01502                         );
01503                     };
01504                 };
01505             }
01506             else // item not ok, drop not on existing item, create new lens/stack
01507             {
01508                 if(m_groupMode==GROUP_LENS)
01509                 {
01510                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01511                         new PanoCommand::NewPartCmd(*m_pano, m_draggingImages, HuginBase::StandardImageVariableGroups::getLensVariables())
01512                     );
01513                 }
01514                 else
01515                 {
01516                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01517                         new PanoCommand::NewPartCmd(*m_pano, m_draggingImages, HuginBase::StandardImageVariableGroups::getStackVariables())
01518                     );
01519                 }
01520             };
01521         }
01522         m_draggingImages.clear();
01523     }
01524     else
01525     {
01526         if (m_optimizerMode && m_leftDownItem.IsOk())
01527         {
01528             int flags;
01529             int col;
01530             wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
01531             // check if left up is on the same item as left down
01532             if (item.IsOk() && item == m_leftDownItem && col == m_leftDownColumn && (flags & wxTREE_HITTEST_ONITEMICON))
01533             {
01534                 HuginBase::UIntSet imgs;
01535                 ImagesTreeData* data = static_cast<ImagesTreeData*>(GetItemData(m_leftDownItem));
01536                 if (data->IsGroup())
01537                 {
01538                     wxTreeItemIdValue cookie;
01539                     wxTreeItemId childItem = GetFirstChild(m_leftDownItem, cookie);
01540                     while (childItem.IsOk())
01541                     {
01542                         data = static_cast<ImagesTreeData*>(GetItemData(childItem));
01543                         imgs.insert(data->GetImgNr());
01544                         childItem = GetNextChild(m_leftDownItem, cookie);
01545                     };
01546                 }
01547                 else
01548                 {
01549                     imgs.insert(data->GetImgNr());
01550                 };
01551                 HuginBase::OptimizeVector optVec = m_pano->getOptimizeVector();
01552                 std::set<std::string> var;
01553                 if (m_columnVector[m_leftDownColumn] == "cam_trans")
01554                 {
01555                     var.insert("TrX");
01556                     var.insert("TrY");
01557                     var.insert("TrZ");
01558                     var.insert("Tpy");
01559                     var.insert("Tpp");
01560                 }
01561                 else
01562                 {
01563                     var.insert(m_columnVector[m_leftDownColumn]);
01564                     if (m_columnVector[m_leftDownColumn] == "Tpy" || m_columnVector[m_leftDownColumn] == "Tpp")
01565                     {
01566                         var.insert("Tpy");
01567                         var.insert("Tpp");
01568                     };
01569                     if (m_columnVector[m_leftDownColumn] == "Vb" || m_columnVector[m_leftDownColumn] == "Vc" || m_columnVector[m_leftDownColumn] == "Vd")
01570                     {
01571                         var.insert("Vb");
01572                         var.insert("Vc");
01573                         var.insert("Vd");
01574                     };
01575                     if (m_columnVector[m_leftDownColumn] == "Vx" || m_columnVector[m_leftDownColumn] == "Vy")
01576                     {
01577                         var.insert("Vx");
01578                         var.insert("Vy");
01579                     };
01580                     if (m_columnVector[m_leftDownColumn] == "Ra" || m_columnVector[m_leftDownColumn] == "Rb" || m_columnVector[m_leftDownColumn] == "Rc" ||
01581                         m_columnVector[m_leftDownColumn] == "Rd" || m_columnVector[m_leftDownColumn] == "Re")
01582                     {
01583                         var.insert("Ra");
01584                         var.insert("Rb");
01585                         var.insert("Rc");
01586                         var.insert("Rd");
01587                         var.insert("Re");
01588                     };
01589                 };
01590                 bool deactivate = false;
01591                 for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
01592                 {
01593                     //search, if image variable is marked for optimise for at least one image of group
01594                     for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end() && !deactivate; ++imgIt)
01595                     {
01596                         if (set_contains(optVec[*imgIt], *varIt))
01597                         {
01598                             deactivate = true;
01599                         };
01600                     };
01601                 };
01602                 // now deactivate or activate the image variable for optimisation
01603                 if (deactivate)
01604                 {
01605                     for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
01606                     {
01607                         for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end(); ++imgIt)
01608                         {
01609                             optVec[*imgIt].erase(*varIt);
01610                         };
01611                     }
01612                 }
01613                 else
01614                 {
01615                     for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
01616                     {
01617                         for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end(); ++imgIt)
01618                         {
01619                             optVec[*imgIt].insert(*varIt);
01620                         };
01621                     };
01622                 };
01623                 PanoCommand::GlobalCmdHist::getInstance().addCommand(
01624                     new PanoCommand::UpdateOptimizeVectorCmd(*m_pano, optVec)
01625                 );
01626                 m_leftDownItem.Unset();
01627                 return;
01628             };
01629         };
01630         if (m_leftDownItem.IsOk())
01631         {
01632             m_leftDownItem.Unset();
01633         };
01634         e.Skip();
01635     };
01636 };
01637 
01638 void ImagesTreeCtrl::OnLeftDown(wxMouseEvent &e)
01639 {
01640     if (!m_dragging)
01641     {
01642         if (e.LeftDown())
01643         {
01644             // force end editing
01645             EndEdit(false);
01646             // find where user clicked
01647             int flags;
01648             int col;
01649             wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
01650             if (item.IsOk() && (flags & wxTREE_HITTEST_ONITEMICON))
01651             {
01652                 if (set_contains(m_editableColumns, col))
01653                 {
01654                     if (!GetItemText(item, col).IsEmpty())
01655                     {
01656                         // store for later and stop processing this event further
01657                         m_leftDownItem = item;
01658                         m_leftDownColumn = col;
01659                         return;
01660                     };
01661                 };
01662             };
01663         };
01664     };
01665     e.Skip();
01666 };
01667 
01668 void ImagesTreeCtrl::OnMouseMove(wxMouseEvent &e)
01669 {
01670     int flags;
01671     int col;
01672     wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
01673     if (item.IsOk() && (flags & wxTREE_HITTEST_ONITEMICON))
01674     {
01675         // mouse moved over optimizer checkbox
01676         int imgNr = GetItemImage(item, col);
01677         if (imgNr >= 0 && imgNr < 2)
01678         {
01679             // update checkbox image and store position for later
01680             SetItemImage(item, col, imgNr + 2);
01681             m_lastCurrentItem = item;
01682             m_lastCurrentCol = col;
01683         };
01684     }
01685     else
01686     {
01687         // mouse moved from checkbox away, so update images
01688         if (m_lastCurrentItem.IsOk())
01689         {
01690             int imgNr = GetItemImage(m_lastCurrentItem, m_lastCurrentCol);
01691             if (imgNr > 1)
01692             {
01693                 SetItemImage(m_lastCurrentItem, m_lastCurrentCol, imgNr - 2);
01694             };
01695             m_lastCurrentItem.Unset();
01696         };
01697     };
01698     e.Skip();
01699 };
01700 
01701 void ImagesTreeCtrl::SelectAllParameters(bool select, bool allImages)
01702 {
01703     std::set<std::string> imgVars;
01704     std::string var=m_columnVector[m_selectedColumn];
01705     if(var=="cam_trans")
01706     {
01707         imgVars.insert("TrX");
01708         imgVars.insert("TrY");
01709         imgVars.insert("TrZ");
01710         imgVars.insert("Tpy");
01711         imgVars.insert("Tpp");
01712     }
01713     else
01714     {
01715         imgVars.insert(var);
01716         if(var=="Vb" || var=="Vc" || var=="Vd")
01717         {
01718             imgVars.insert("Vb");
01719             imgVars.insert("Vc");
01720             imgVars.insert("Vd");
01721         };
01722         if(var=="Vx" || var=="Vy")
01723         {
01724             imgVars.insert("Vx");
01725             imgVars.insert("Vy");
01726         };
01727         if(var=="Ra" || var=="Rb" || var=="Rc" || var=="Rd" || var=="Re")
01728         {
01729             imgVars.insert("Ra");
01730             imgVars.insert("Rb");
01731             imgVars.insert("Rc");
01732             imgVars.insert("Rd");
01733             imgVars.insert("Re");
01734         };
01735 
01736     };
01737 
01738     HuginBase::UIntSet imgs;
01739     if(allImages)
01740     {
01741         fill_set(imgs, 0, m_pano->getNrOfImages()-1);
01742     }
01743     else
01744     {
01745         wxArrayTreeItemIds selectedItem;
01746         if(GetSelections(selectedItem)>0)
01747         {
01748             for(size_t i=0;i<selectedItem.size();i++)
01749             {
01750                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(selectedItem[i]));
01751                 wxTreeItemId startItem;
01752                 if(data->IsGroup())
01753                 {
01754                     startItem=selectedItem[i];
01755                 }
01756                 else
01757                 {
01758                     startItem=GetItemParent(selectedItem[i]);
01759                 };
01760                 wxTreeItemIdValue cookie;
01761                 wxTreeItemId item=GetFirstChild(startItem,cookie);
01762                 while(item.IsOk())
01763                 {
01764                     data=static_cast<ImagesTreeData*>(GetItemData(item));
01765                     imgs.insert(data->GetImgNr());
01766                     item=GetNextChild(startItem, cookie);
01767                 };
01768             };
01769         };
01770     };
01771 
01772     HuginBase::OptimizeVector optVec = m_pano->getOptimizeVector();
01773     for(HuginBase::UIntSet::iterator img=imgs.begin(); img!=imgs.end(); ++img)
01774     {
01775         for(std::set<std::string>::const_iterator it=imgVars.begin(); it!=imgVars.end(); ++it)
01776         {
01777             if(select)
01778             {
01779                 if((*it=="y" || *it=="p" || *it=="r" || *it=="TrX" || *it=="TrY" || *it=="TrZ" || *it=="Tpy" || *it=="Tpp") && 
01780                     *img==m_pano->getOptions().optimizeReferenceImage)
01781                 {
01782                     optVec[*img].erase(*it);
01783                     continue;
01784                 };
01785                 if((*it=="Eev" || *it=="Er" || *it=="Eb") && *img==m_pano->getOptions().colorReferenceImage)
01786                 {
01787                     optVec[*img].erase(*it);
01788                     continue;
01789                 };
01790                 optVec[*img].insert(*it);
01791             }
01792             else
01793             {
01794                 optVec[*img].erase(*it);
01795             };
01796         };
01797     };
01798     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01799         new PanoCommand::UpdateOptimizeVectorCmd(*m_pano, optVec)
01800     );
01801 };
01802 
01803 void ImagesTreeCtrl::OnSelectAll(wxCommandEvent &e)
01804 {
01805     SelectAllParameters(true, true);
01806 };
01807 
01808 void ImagesTreeCtrl::OnUnselectAll(wxCommandEvent &e)
01809 {
01810     SelectAllParameters(false, true);
01811 };
01812 
01813 void ImagesTreeCtrl::OnSelectLensStack(wxCommandEvent &e)
01814 {
01815     SelectAllParameters(true, false);
01816 };
01817 
01818 void ImagesTreeCtrl::OnUnselectLensStack(wxCommandEvent &e)
01819 {
01820     SelectAllParameters(false, false);
01821 };
01822 
01823 void ImagesTreeCtrl::OnChar(wxTreeEvent &e)
01824 {
01825     switch(e.GetKeyCode())
01826     {
01827         case WXK_INSERT:
01828             {
01829                 wxCommandEvent ev(wxEVT_COMMAND_MENU_SELECTED, XRCID("action_add_images"));
01830                 MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
01831                 break;
01832             };
01833         case WXK_DELETE:
01834             {
01835                 HuginBase::UIntSet imgs=GetSelectedImages();
01836                 if(imgs.size()>0)
01837                 {
01838                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01839                         new PanoCommand::RemoveImagesCmd(*m_pano, imgs)
01840                     );
01841                 };
01842                 break;
01843             };
01844 #if defined __WXMAC__
01845         case 'A':
01846         case 'a':
01847             // check for cmd+A -> select all
01848             if (e.GetExtraLong() == wxMOD_CMD)
01849             {
01850                 SelectAll();
01851             };
01852             break;
01853 #endif
01854         case 1: //Ctrl+A
01855             {
01856                 SelectAll();
01857                 break;
01858             }
01859         default:
01860             e.Skip();
01861     };
01862 };
01863 
01864 void ImagesTreeCtrl::OnBeginEdit(wxTreeEvent &e)
01865 {
01866     m_editOldString=GetItemText(e.GetItem(), e.GetInt());
01867     if(m_editOldString.IsEmpty())
01868     {
01869         e.Veto();
01870     }
01871     else
01872     {
01873         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
01874         if(data->IsGroup())
01875         {
01876             wxTreeItemIdValue cookie;
01877             wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
01878             data=static_cast<ImagesTreeData*>(GetItemData(item));
01879         };
01880         m_editVal=m_pano->getImage(data->GetImgNr()).getVar(m_columnVector[e.GetInt()]);
01881         SetItemText(e.GetItem(), e.GetInt(), hugin_utils::doubleTowxString(m_editVal));
01882         e.Allow();
01883     };
01884 };
01885 
01886 void ImagesTreeCtrl::OnEndEdit(wxTreeEvent &e)
01887 {
01888     if(e.IsEditCancelled())
01889     {
01890         //restore old string
01891         SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01892         Refresh();
01893     }
01894     else
01895     {
01896         double val;
01897         if(!hugin_utils::str2double(e.GetLabel(),val))
01898         {
01899             //restore old string
01900             SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01901             Refresh();
01902             e.Veto();
01903         }
01904         else
01905         {
01906             //only update if value was changed
01907             if(val!=m_editVal)
01908             {
01909                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
01910                 if(data->IsGroup())
01911                 {
01912                     wxTreeItemIdValue cookie;
01913                     wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
01914                     data=static_cast<ImagesTreeData*>(GetItemData(item));
01915                 };
01916                 HuginBase::UIntSet imgs;
01917                 imgs.insert(data->GetImgNr());
01918                 if(m_columnVector[e.GetInt()]=="v")
01919                 {
01920                     if(m_pano->getImage(data->GetImgNr()).getProjection()==HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC && val>190)
01921                     {
01922                         if(wxMessageBox(
01923                             wxString::Format(_("You have given a field of view of %.2f degrees.\n But the orthographic projection is limited to a field of view of 180 degress.\nDo you want still use that high value?"), val),
01924 #ifdef __WXMSW__
01925                             _("Hugin"),
01926 #else
01927                             wxT(""),
01928 #endif
01929                             wxICON_EXCLAMATION | wxYES_NO)==wxNO)
01930                         {
01931                             //restore old string
01932                             SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01933                             Refresh();
01934                             e.Veto();
01935                             e.Skip();
01936                             return;
01937                         };
01938                     };
01939                 };
01940                 HuginBase::Variable var(m_columnVector[e.GetInt()], val);
01941                 PanoCommand::GlobalCmdHist::getInstance().addCommand(
01942                     new PanoCommand::SetVariableCmd(*m_pano, imgs, var)
01943                 );
01944                 //we need to veto the event otherwise the internal
01945                 //function does update the text to the full number
01946                 e.Veto();
01947             }
01948             else
01949             {
01950                 //restore old string
01951                 SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01952                 Refresh();
01953             };
01954         };
01955     };
01956     e.Skip();
01957 };
01958 
01959 void ImagesTreeCtrl::OnExecuteOperation(wxCommandEvent & e)
01960 {
01961     PanoOperation::PanoOperation* op=m_menuOperation[e.GetId()];
01962     PanoCommand::PanoCommand* cmd=op->GetCommand(this,*m_pano, GetSelectedImages(), m_guiLevel);
01963     if(cmd!=NULL)
01964     {
01965         PanoCommand::GlobalCmdHist::getInstance().addCommand(cmd);
01966     };
01967 };
01968 
01969 void ImagesTreeCtrl::OnLeftDblClick(wxMouseEvent &e)
01970 {
01971     if(!m_optimizerMode)
01972     {
01973         int flags;
01974         int col;
01975         wxTreeItemId item=HitTest(e.GetPosition(), flags, col);
01976         m_selectedColumn=col;
01977         wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, ID_EDIT);
01978         GetEventHandler()->AddPendingEvent(commandEvent);
01979     };
01980     e.Skip();
01981 };
01982 
01983 IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrl, wxTreeListCtrl)
01984 
01985 ImagesTreeCtrlXmlHandler::ImagesTreeCtrlXmlHandler()
01986     : wxTreeListCtrlXmlHandler()
01987 {
01988 }
01989 
01990 wxObject *ImagesTreeCtrlXmlHandler::DoCreateResource()
01991 {
01992     XRC_MAKE_INSTANCE(cp, ImagesTreeCtrl)
01993 
01994     cp->Create(m_parentAsWindow,
01995                GetID(),
01996                GetPosition(), GetSize(),
01997                GetStyle(wxT("style")),
01998                GetName());
01999 
02000     SetupWindow( cp);
02001 
02002     return cp;
02003 }
02004 
02005 bool ImagesTreeCtrlXmlHandler::CanHandle(wxXmlNode *node)
02006 {
02007     return IsOfClass(node, wxT("ImagesTreeList"));
02008 }
02009 
02010 IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrlXmlHandler, wxTreeListCtrlXmlHandler)
02011 
02012       

Generated on 27 May 2017 for Hugintrunk by  doxygen 1.4.7