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

Generated on 9 Feb 2016 for Hugintrunk by  doxygen 1.4.7