ImagesList.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00027 #include <config.h>
00028 #include "panoinc_WX.h"
00029 #include "panoinc.h"
00030 
00031 #include "base_wx/wxPlatform.h"
00032 #include "hugin/ImagesList.h"
00033 #include "base_wx/wxImageCache.h"
00034 #include "base_wx/platform.h"
00035 
00036 #ifdef __WXMAC__
00037 #include "hugin/MainFrame.h"
00038 #endif
00039 
00040 using namespace PT;
00041 using namespace hugin_utils;
00042 
00043 #if wxCHECK_VERSION(2,9,0)
00044     wxDEFINE_EVENT(EVT_IMAGE_ADD,wxCommandEvent);
00045     wxDEFINE_EVENT(EVT_IMAGE_DEL,wxCommandEvent);
00046 #else
00047 #if _WINDOWS && defined Hugin_shared
00048     DEFINE_LOCAL_EVENT_TYPE(EVT_IMAGE_ADD)
00049     DEFINE_LOCAL_EVENT_TYPE(EVT_IMAGE_DEL)
00050 #else
00051     DEFINE_EVENT_TYPE(EVT_IMAGE_ADD)
00052     DEFINE_EVENT_TYPE(EVT_IMAGE_DEL)
00053 #endif
00054 #endif
00055 
00056 //------------------------------------------------------------------------------
00057 
00058 BEGIN_EVENT_TABLE(ImagesList, wxListCtrl)
00059     EVT_LIST_ITEM_SELECTED(-1, ImagesList::OnItemSelected)
00060     EVT_LIST_ITEM_DESELECTED(-1, ImagesList::OnItemDeselected)
00061     EVT_LIST_COL_END_DRAG(-1, ImagesList::OnColumnWidthChange)
00062     EVT_CHAR(ImagesList::OnChar)
00063 END_EVENT_TABLE()
00064 
00065 // Define a constructor for the Images Panel
00066 ImagesList::ImagesList()
00067 {
00068     pano = 0;
00069 }
00070 
00071 bool ImagesList::Create(wxWindow* parent, wxWindowID id,
00072                         const wxPoint& pos,
00073                         const wxSize& size,
00074                         long style,
00075                         const wxString& name)
00076 {
00077     DEBUG_TRACE("List");
00078     if (! wxListCtrl::Create(parent, id, pos, size, wxLC_REPORT | style) ) {
00079         return false;
00080     }
00081 
00082     DEBUG_TRACE("List, adding columns");
00083 
00084     m_notifyParents = true;
00085     InsertColumn( 0, wxT("#"), wxLIST_FORMAT_RIGHT, 35 );
00086 
00087     // get a good size for the images
00088     wxPoint sz(1,11);
00089     sz = ConvertDialogToPixels(sz);
00090     m_iconHeight = sz.y;
00091     DEBUG_DEBUG("icon Height: " << m_iconHeight);
00092 
00093     //m_smallIcons = new wxImageList(m_iconHeight, m_iconHeight);
00094     //AssignImageList(m_smallIcons,wxIMAGE_LIST_SMALL);
00095     DEBUG_TRACE("");
00096     m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigits"),1);
00097     m_pixelDigits = wxConfigBase::Get()->Read(wxT("/General/PixelFractionalDigits"),1);
00098     m_distDigits = wxConfigBase::Get()->Read(wxT("/General/DistortionFractionalDigits"),3);
00099     m_singleSelect=(style & wxLC_SINGLE_SEL)!=0;
00100     return true;
00101 }
00102 
00103 void ImagesList::Init(PT::Panorama * panorama)
00104 {
00105     pano = panorama;
00106     pano->addObserver(this);
00107     
00109     variable_groups = new HuginBase::StandardImageVariableGroups(*pano);
00110     DEBUG_ASSERT(variable_groups);
00111     
00112 #ifdef __WXMAC__
00113     SetDropTarget(new PanoDropTarget(*pano, true));
00114 #endif
00115 }
00116 
00117 ImagesList::~ImagesList(void)
00118 {
00119     DEBUG_TRACE("");
00120     pano->removeObserver(this);
00121     delete variable_groups;
00122 }
00123 
00124 void ImagesList::panoramaImagesChanged(Panorama &pano, const UIntSet &changed)
00125 {
00126     DEBUG_TRACE("");
00127 
00128     Freeze();
00129     m_notifyParents = false;
00130     unsigned int nrImages = pano.getNrOfImages();
00131     unsigned int nrItems = GetItemCount();
00132 
00133     // remove items for nonexisting images
00134     for (int i=nrItems-1; i>=(int)nrImages; i--)
00135     {
00136         DEBUG_DEBUG("Deleting list item " << i);
00137 
00138         // deselect item
00139         DEBUG_DEBUG("item state before: " << GetItemState(i,wxLIST_STATE_SELECTED));
00140         SetItemState(i,0, wxLIST_STATE_SELECTED);
00141         DEBUG_DEBUG("item state after: " << GetItemState(i,wxLIST_STATE_SELECTED));
00142 
00143         RemoveItem(i);
00144         //m_smallIcons->Remove(i);
00145     }
00146     
00147     // Make sure the part numbers are up to date before writing them to the table.
00148     variable_groups->update();
00149 
00150     // update existing items
00151 //    if ( nrImages >= nrItems ) {
00152         for(UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
00153             if (*it >= nrItems) {
00154                 // create new item.
00155                 DEBUG_DEBUG("creating " << *it);
00156                 wxBitmap small0(m_iconHeight, m_iconHeight);
00157                 //createIcon(small0, *it, m_iconHeight);
00158                 //m_smallIcons->Add(small0);
00159 
00160                 CreateItem(*it);
00161 
00162             } else {
00163                 // update existing item
00164                 DEBUG_DEBUG("updating item" << *it);
00165                 wxBitmap small0(m_iconHeight, m_iconHeight);
00166                 //createIcon(small0, *it, m_iconHeight);
00167                 //m_smallIcons->Replace(*it, small0);
00168 
00169                 UpdateItem(*it);
00170             }
00171             ImageCache::getInstance().softFlush();
00172         }
00173 //    }
00174     
00175     // Update the part numbers. We do this for every image, as the images that
00176     // have changed may affect the part numbers for images that haven't changed.
00177     for (unsigned int i = 0; i < pano.getNrOfImages(); i++)
00178     {
00179         UpdatePartNumbersForItem(i);
00180     }
00181     
00182     Thaw();
00183     m_notifyParents = true;
00184     
00185     // HACK! need to notify clients anyway... send dummy event..
00186     // lets hope our clients query for the selected images with GetSelected()
00187     // and do not try to interpret the event.
00188     wxListEvent e;
00189     e.SetEventType(wxEVT_COMMAND_LIST_ITEM_SELECTED);
00190     e.m_itemIndex = -1;
00191     GetEventHandler()->ProcessEvent(e);
00192 }
00193 
00194 const UIntSet & ImagesList::GetSelected() const      
00195 { 
00196     return selectedItems; 
00197 }
00198 
00199 #if 0
00200 void ImagesList::createIcon(wxBitmap & bitmap, unsigned int imgNr, unsigned int size)
00201 {
00202     ImageCache::Entry * cacheEntry = ImageCache::getInstance().getSmallImage(
00203             pano->getImage(imgNr).getFilename());
00204     if (! cacheEntry) {
00205         return;
00206     }
00207     wxImage * s_img = cacheEntry->image; 
00208     if (!s_img->Ok()) {
00209         return;
00210     }
00211 
00212     float w = s_img->GetWidth();
00213     float h = s_img->GetHeight();
00214 
00215     // create scaled versions
00216     int bW,bH;
00217 
00218     if ( h > w ) {
00219         // portrait
00220         bW = roundi(w/h * size);
00221         bH = size;
00222     } else {
00223         // landscape
00224         bW = size;
00225         bH = roundi(h/w * size);
00226     }
00227     wxImage img = s_img->Scale(bW, bH);
00228     wxBitmap bimg(img);
00229 
00230     wxMemoryDC temp_dc;
00231     temp_dc.SelectObject(bitmap);
00232     temp_dc.Clear();
00233 /*
00234     wxBitmap maskb(size, size);
00235     wxMemoryDC mask_dc;
00236     mask_dc.SelectObject(maskb);
00237     mask_dc.Clear();
00238     mask_dc.SetBrush(wxBrush("WHITE",wxSOLID));
00239     mask_dc.SetPen(wxPen("WHITE",wxSOLID));
00240 */
00241     if (h > w) {
00242         temp_dc.DrawBitmap(bimg, (size-bW)>>1 ,0);
00243     } else {
00244         temp_dc.DrawBitmap(bimg,0,(size-bH)>>1);
00245     }
00246 //    wxMask * m = new wxMask(bitmap, wxColour(0,0,0));
00247 //    bitmap.SetMask(m);
00248 }
00249 #endif
00250 
00251 void ImagesList::CreateItem(unsigned int imgNr)
00252 {
00253     DEBUG_DEBUG("creating item " << imgNr);
00254     // create the new row
00255     InsertItem ( imgNr, wxString::Format(wxT("%d"),imgNr), imgNr );
00256     UpdateItem(imgNr);
00257 }
00258 
00259 void ImagesList::RemoveItem(unsigned int imgNr)
00260 {
00261     // call wxListCtrl's removal function
00262     wxListCtrl::DeleteItem(imgNr);
00263 }
00264 
00265 void ImagesList::SelectSingleImage(unsigned int imgNr)
00266 {
00267     unsigned int nrItems = GetItemCount();
00268     for (unsigned int i=0; i < nrItems ; i++) {
00269         int selected = GetItemState(i, wxLIST_STATE_SELECTED);
00270         if (i != imgNr && selected) {
00271             SetItemState(i, 0, wxLIST_STATE_SELECTED);
00272         }
00273     }
00274     SetItemState(imgNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
00275 }
00276 
00277 void ImagesList::SelectImages(const HuginBase::UIntSet imgs)
00278 {
00279     unsigned int nrItems = GetItemCount();
00280     for (unsigned int i=0; i < nrItems ; i++){
00281         if(set_contains(imgs, i))
00282         {
00283             SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
00284         }
00285         else
00286         {
00287             SetItemState(i, 0, wxLIST_STATE_SELECTED);
00288         };
00289     }
00290     SetItemState(*imgs.begin(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
00291     selectedItems=imgs;
00292 }
00293 
00294 void ImagesList::SelectImageRange(unsigned int imgStart,unsigned int imgEnd)
00295 {
00296     size_t nrItems = GetItemCount();
00297     size_t _imgStart=imgStart;
00298     size_t _imgEnd=imgEnd;
00299     if(imgEnd<imgStart)
00300     {
00301         _imgStart=imgEnd;
00302         _imgEnd=imgStart;
00303     }
00304     for (size_t i=0; i < nrItems ; i++)
00305     {
00306         int selected = GetItemState(i, wxLIST_STATE_SELECTED);
00307         if ((i < _imgStart || i>_imgEnd ) && selected)
00308         {
00309             SetItemState(i, 0, wxLIST_STATE_SELECTED);
00310         }
00311     }
00312     for(size_t i=_imgStart; i<=_imgEnd; i++)
00313     {
00314         SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
00315     };
00316 };
00317 
00318 void ImagesList::SelectAll()
00319 {
00320     unsigned int nrItems = GetItemCount();
00321     for (unsigned int i=0; i < nrItems ; i++)
00322     {
00323         SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
00324     }
00325 }
00326 
00327 void ImagesList::DeselectAll()
00328 {
00329     unsigned int nrItems = GetItemCount();
00330     for (unsigned int i=0; i < nrItems ; i++) {
00331         int selected = GetItemState(i, wxLIST_STATE_SELECTED);
00332         if (selected) {
00333             SetItemState(i, 0, wxLIST_STATE_SELECTED);
00334         }
00335     }
00336 }
00337 
00338 void ImagesList::OnItemSelected ( wxListEvent & e )
00339 {
00340     DEBUG_TRACE(e.GetIndex());
00341     if(e.GetIndex() < 0) return;
00342     selectedItems.insert((int)e.GetIndex());
00343     // allow other parents to receive this event, only if its
00344     // generated by the user, and not during an automatic update
00345     // triggered by a change to the panorama
00346     if (m_notifyParents) {
00347         e.Skip();
00348     }
00349 }
00350 
00351 void ImagesList::OnChar(wxKeyEvent &e)
00352 {
00353     switch(e.GetKeyCode())
00354     {
00355         case WXK_INSERT:
00356             {
00357                 wxCommandEvent ev(EVT_IMAGE_ADD,wxID_ANY);
00358                 GetParent()->GetEventHandler()->AddPendingEvent(ev);
00359                 break;
00360             };
00361         case WXK_DELETE:
00362             {
00363                 wxCommandEvent ev(EVT_IMAGE_DEL,wxID_ANY);
00364                 GetParent()->GetEventHandler()->AddPendingEvent(ev);
00365                 break;
00366             };
00367         case 1: //Ctrl+A
00368             {
00369                 if(!m_singleSelect && e.CmdDown())
00370                 {
00371                     SelectAll();
00372                 }
00373                 break;
00374             }
00375     };
00376     e.Skip();
00377 };
00378 
00379 
00380 void ImagesList::OnItemDeselected ( wxListEvent & e )
00381 {
00382     DEBUG_TRACE(e.GetIndex());
00383     if(e.GetIndex() < 0) return;
00384     selectedItems.erase((int)e.GetIndex());
00385     // allow other parents to receive this event, only if its
00386     // generated by the user, and not during an automatic update
00387     // triggered by a change to the panorama
00388     if (m_notifyParents) {
00389         e.Skip();
00390     }
00391 }
00392 
00393 #if 0
00394 void ImagesList::OnItemSelected ( wxListEvent & e )
00395 {
00396     DEBUG_TRACE("");
00397 
00398     // publicate the selected items
00399     selectedImages.clear();
00400 
00401     for ( int Nr=GetItemCount()-1 ; Nr>=0 ; --Nr ) {
00402         if ( GetItemState( Nr, wxLIST_STATE_SELECTED ) ) {
00403             selectedImages.insert(Nr);
00404         }
00405     }
00406     // notify other parties about changed notification..
00407 
00408     // let others recieve the event too
00409     e.Skip(true);
00410     DEBUG_TRACE("end");
00411 }
00412 #endif
00413 
00414 void ImagesList::OnColumnWidthChange( wxListEvent & e )
00415 {
00416     if(m_configClassName != wxT(""))
00417     {
00418         int colNum = e.GetColumn();
00419         wxConfigBase::Get()->Write( m_configClassName+wxString::Format(wxT("/ColumnWidth%d"),colNum), GetColumnWidth(colNum) );
00420     }
00421 }
00422 
00423 void ImagesList::UpdateItem(unsigned int imgNr)
00424 {
00425 
00426 }
00427 
00428 void ImagesList::UpdatePartNumbersForItem(unsigned int imgNr)
00429 {
00430 
00431 }
00432 
00433 IMPLEMENT_DYNAMIC_CLASS(ImagesList, wxListCtrl)
00434 
00435 // ============================================================================
00436 // ============================================================================
00437 // Mask
00438 
00439 ImagesListMask::ImagesListMask()
00440 {
00441 }
00442 
00443 bool ImagesListMask::Create(wxWindow* parent, wxWindowID id,
00444                              const wxPoint& pos,
00445                              const wxSize& size,
00446                              long style,
00447                              const wxString& name)
00448 {
00449     DEBUG_TRACE("");
00450     if (!ImagesList::Create(parent, id, pos, size, wxLC_SINGLE_SEL | style, name))
00451         return false;
00452 
00453     m_configClassName = wxT("/ImagesListMask");
00454 
00455     InsertColumn(1, _("Filename"), wxLIST_FORMAT_LEFT, 200 );
00456     InsertColumn(2, _("Number of masks"), wxLIST_FORMAT_RIGHT,120);
00457     InsertColumn(3, _("Crop"), wxLIST_FORMAT_RIGHT,120);
00458 
00459     //get saved width
00460     for ( int j=0; j < GetColumnCount() ; j++ )
00461     {
00462         // -1 is auto
00463         int width = wxConfigBase::Get()->Read(wxString::Format(m_configClassName+wxT("/ColumnWidth%d"), j ), -1);
00464         if(width != -1)
00465             SetColumnWidth(j, width);
00466     }
00467     return true;
00468 }
00469 
00470 
00471 void ImagesListMask::Init(PT::Panorama * panorama)
00472 {
00473     ImagesList::Init(panorama);
00474 }
00475 
00476 void ImagesListMask::UpdateItem(unsigned int imgNr)
00477 {
00478     const SrcPanoImage & img = pano->getImage(imgNr);
00479     wxFileName fn(wxString (img.getFilename().c_str(), HUGIN_CONV_FILENAME));
00480     SetItem(imgNr, 1, fn.GetFullName() );
00481 
00482     wxString maskstr;
00483     if(img.hasMasks())
00484         maskstr=wxString::Format(wxT("%lu"), (unsigned long int) pano->getImage(imgNr).getMasks().size());
00485     else
00486         maskstr=wxT("-");
00487     SetItem(imgNr, 2, maskstr);
00488 
00489     wxString cropstr(wxT("-"));
00490     if ( img.getCropMode() != SrcPanoImage::NO_CROP )
00491     {
00492         vigra::Rect2D c = img.getCropRect();
00493         cropstr.Printf(wxT("%d,%d,%d,%d"), c.left(), c.right(), c.top(), c.bottom());
00494     }
00495     SetItem(imgNr, 3, cropstr);
00496 }
00497 
00498 void ImagesListMask::SetSingleSelect(bool isSingleSelect)
00499 {
00500     if(isSingleSelect)
00501     {
00502         SetSingleStyle(wxLC_SINGLE_SEL, true);
00503     }
00504     else
00505     {
00506         SetSingleStyle(wxLC_SINGLE_SEL, false);
00507     };
00508     m_singleSelect=(GetWindowStyle() & wxLC_SINGLE_SEL)!=0;
00509 
00510 #ifdef __WXGTK__
00511     // wxGTK shows a bad behaviour, if we change the style
00512     // all items and columns are deleted, we need to create it again
00513     Freeze();
00514     InsertColumn(0, wxT("#"), wxLIST_FORMAT_RIGHT, 35 );
00515     InsertColumn(1, _("Filename"), wxLIST_FORMAT_LEFT, 200 );
00516     InsertColumn(2, _("Number of masks"), wxLIST_FORMAT_RIGHT,120);
00517     InsertColumn(3, _("Crop"), wxLIST_FORMAT_RIGHT,120);
00518 
00519     //get saved width
00520     for ( int j=0; j < GetColumnCount() ; j++ )
00521     {
00522         // -1 is auto
00523         int width = wxConfigBase::Get()->Read(wxString::Format(m_configClassName+wxT("/ColumnWidth%d"), j ), -1);
00524         if(width != -1)
00525             SetColumnWidth(j, width);
00526     }
00527 
00528     for(size_t i=0; i<pano->getNrOfImages(); i++)
00529     {
00530         CreateItem(i);
00531     };
00532     //restore selection
00533     if(selectedItems.size()>0)
00534     {
00535         if(m_singleSelect)
00536         {
00537             size_t imgNr=*selectedItems.begin();
00538             selectedItems.clear();
00539             selectedItems.insert(imgNr);
00540         }
00541         SelectImages(selectedItems);
00542     };
00543     Thaw();
00544 #endif
00545 };
00546 
00547 IMPLEMENT_DYNAMIC_CLASS(ImagesListMask, ImagesList)
00548 
00549 ImagesListMaskXmlHandler::ImagesListMaskXmlHandler()
00550     : wxXmlResourceHandler()
00551 {
00552     AddWindowStyles();
00553 }
00554 
00555 wxObject *ImagesListMaskXmlHandler::DoCreateResource()
00556 {
00557     XRC_MAKE_INSTANCE(cp, ImagesListMask)
00558 
00559     cp->Create(m_parentAsWindow,
00560                GetID(),
00561                GetPosition(), GetSize(),
00562                GetStyle(wxT("style")),
00563                GetName());
00564 
00565     SetupWindow( cp);
00566 
00567     return cp;
00568 }
00569 
00570 bool ImagesListMaskXmlHandler::CanHandle(wxXmlNode *node)
00571 {
00572     return IsOfClass(node, wxT("ImagesListMask"));
00573 }
00574 
00575 IMPLEMENT_DYNAMIC_CLASS(ImagesListMaskXmlHandler, wxXmlResourceHandler)
00576 

Generated on Mon Sep 22 01:25:33 2014 for Hugintrunk by  doxygen 1.3.9.1