Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PreviewFrame.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 #include "hugin_config.h"
28 
29 #include "panoinc_WX.h"
30 
31 #include "panoinc.h"
32 
33 #include "base_wx/platform.h"
34 #include "base_wx/wxutils.h"
35 #include "hugin/config_defaults.h"
36 #include "hugin/PreviewFrame.h"
37 #include "hugin/huginApp.h"
38 #include "hugin/PreviewPanel.h"
39 #include "hugin/ImagesPanel.h"
40 #include "base_wx/CommandHistory.h"
41 #include "base_wx/PanoCommand.h"
45 #include "base_wx/wxPlatform.h"
46 
48 
49 extern "C" {
50 #include <pano13/queryfeature.h>
51 }
52 
53 // a random id, hope this doesn't break something..
54 enum {
55  ID_PROJECTION_CHOICE = wxID_HIGHEST +1,
64  ID_TOGGLE_BUT = wxID_HIGHEST+100,
65  PROJ_PARAM_NAMES_ID = wxID_HIGHEST+1000,
66  PROJ_PARAM_VAL_ID = wxID_HIGHEST+1100,
67  PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1200,
68  PROJ_PARAM_RESET_ID = wxID_HIGHEST+1250,
69  ID_FULL_SCREEN = wxID_HIGHEST+1700,
70  ID_UNDO = wxID_HIGHEST+1701,
71  ID_REDO = wxID_HIGHEST+1702
72 };
73 
74 #define PF_STYLE (wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN)
75 
77  : wxFrame(frame,-1, _("Panorama preview"), wxDefaultPosition, wxDefaultSize,
78  PF_STYLE),
79  m_pano(pano)
80 {
81  DEBUG_TRACE("");
82 
83  m_oldProjFormat = -1;
84  m_ToolBar = wxXmlResource::Get()->LoadToolBar(this, wxT("preview_toolbar"));
86  // create tool bar
87  SetToolBar(m_ToolBar);
88 
89  m_topsizer = new wxBoxSizer( wxVERTICAL );
90 
91  m_ToggleButtonSizer = new wxStaticBoxSizer(
92  new wxStaticBox(this, -1, _("displayed images")),
93  wxHORIZONTAL );
94 
95  m_ButtonPanel = new wxScrolledWindow(this, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
96  // Set min height big enough to display scrollbars as well
97  m_ButtonPanel->SetSizeHints(20, 42);
98  //Horizontal scroll bars only
99  m_ButtonPanel->SetScrollRate(10, 0);
100  m_ButtonSizer = new wxBoxSizer(wxHORIZONTAL);
101  m_ButtonPanel->SetAutoLayout(true);
102  m_ButtonPanel->SetSizer(m_ButtonSizer);
103 
104  m_ToggleButtonSizer->Add(m_ButtonPanel, 1, wxEXPAND, 0);
105 
106  m_topsizer->Add(m_ToggleButtonSizer, 0, wxEXPAND | wxALL, 5);
107 
108  wxFlexGridSizer * flexSizer = new wxFlexGridSizer(2,0,5,5);
109  flexSizer->AddGrowableCol(0);
110  flexSizer->AddGrowableRow(0);
111 
112  // create our preview panel
114  m_PreviewPanel->Create(this);
115  m_PreviewPanel->Init(this, &pano);
116 
117  flexSizer->Add(m_PreviewPanel,
118  1, // not vertically stretchable
119  wxEXPAND | // horizontally stretchable
120  wxALL, // draw border all around
121  5); // border width
122 
123 
124  m_VFOVSlider = new wxSlider(this, -1, 1,
125  1, 180,
126  wxDefaultPosition, wxDefaultSize,
127  wxSL_VERTICAL | wxSL_AUTOTICKS,
128  wxDefaultValidator,
129  _("VFOV"));
130  m_VFOVSlider->SetLineSize(2);
131  m_VFOVSlider->SetPageSize(10);
132  m_VFOVSlider->SetTickFreq(5);
133  m_VFOVSlider->SetToolTip(_("drag to change the vertical field of view"));
134 
135  flexSizer->Add(m_VFOVSlider, 0, wxEXPAND);
136 
137  m_HFOVSlider = new wxSlider(this, -1, 1,
138  1, 360,
139  wxDefaultPosition, wxDefaultSize,
140  wxSL_HORIZONTAL | wxSL_AUTOTICKS,
141  wxDefaultValidator,
142  _("HFOV"));
143  m_HFOVSlider->SetPageSize(10);
144  m_HFOVSlider->SetLineSize(2);
145  m_HFOVSlider->SetTickFreq(5);
146 
147  m_HFOVSlider->SetToolTip(_("drag to change the horizontal field of view"));
148 
149  flexSizer->Add(m_HFOVSlider, 0, wxEXPAND);
150 
151  m_topsizer->Add(flexSizer,
152  1, // vertically stretchable
153  wxEXPAND | // horizontally stretchable
154  wxALL, // draw border all around
155  5); // border width
156 
157  wxStaticBoxSizer * blendModeSizer = new wxStaticBoxSizer(
158  new wxStaticBox(this, -1, _("Preview Options")),
159  wxHORIZONTAL);
160 
161  blendModeSizer->Add(new wxStaticText(this, -1, _("projection (f):")),
162  0, // not vertically strechable
163  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
164  5); // border width
165  m_ProjectionChoice = new wxChoice(this, ID_PROJECTION_CHOICE,
166  wxDefaultPosition, wxDefaultSize);
167  m_ProjectionChoice->Bind(wxEVT_CHOICE, &PreviewFrame::OnProjectionChoice, this);
168 
169  /* populate with all available projection types */
170  int nP = panoProjectionFormatCount();
171  for(int n=0; n < nP; n++) {
172  pano_projection_features proj;
173  if (panoProjectionFeaturesQuery(n, &proj)) {
174  wxString str2(proj.name, wxConvLocal);
175  m_ProjectionChoice->Append(wxGetTranslation(str2));
176  }
177  }
178  m_ProjectionChoice->SetSelection(2);
179 
180  blendModeSizer->Add(m_ProjectionChoice,
181  0,
182  wxALL | wxALIGN_CENTER_VERTICAL,
183  5);
184 
186  // Blend mode
187  blendModeSizer->Add(new wxStaticText(this, -1, _("Blend mode:")),
188  0, // not vertically strechable
189  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
190  5); // border width
191 
192  m_choices[0] = _("normal");
193  m_choices[1] = _("difference");
194 
195  int oldMode = wxConfigBase::Get()->Read(wxT("/PreviewFrame/blendMode"), 0l);
196  if (oldMode > 1) oldMode = 0;
197  m_BlendModeChoice = new wxChoice(this, ID_BLEND_CHOICE,
198  wxDefaultPosition, wxDefaultSize,
199  2, m_choices);
200  m_BlendModeChoice->SetSelection((PreviewPanel::BlendMode) oldMode);
201  m_BlendModeChoice->Bind(wxEVT_CHOICE, &PreviewFrame::OnBlendChoice, this);
202 
203  blendModeSizer->Add(m_BlendModeChoice,
204  0,
205  wxALL | wxALIGN_CENTER_VERTICAL,
206  5);
207 
209  // LDR, HDR
210  blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")),
211  0, // not vertically strechable
212  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
213  5); // border width
214 
215  m_choices[0] = _("LDR");
216  m_choices[1] = _("HDR");
217  m_outputModeChoice = new wxChoice(this, ID_OUTPUTMODE_CHOICE,
218  wxDefaultPosition, wxDefaultSize,
219  2, m_choices);
220  m_outputModeChoice->SetSelection(0);
221  m_outputModeChoice->Bind(wxEVT_CHOICE, &PreviewFrame::OnOutputChoice, this);
222  blendModeSizer->Add(m_outputModeChoice,
223  0,
224  wxALL | wxALIGN_CENTER_VERTICAL,
225  5);
226 
228  // exposure
229  blendModeSizer->Add(new wxStaticText(this, -1, _("EV:")),
230  0, // not vertically strechable
231  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
232  5); // border width
233 
234  m_defaultExposureBut = new wxBitmapButton(this, ID_EXPOSURE_DEFAULT,
235  wxArtProvider::GetBitmap(wxART_REDO));
236  m_defaultExposureBut->Bind(wxEVT_BUTTON, &PreviewFrame::OnDefaultExposure, this);
237 
238  blendModeSizer->Add(m_defaultExposureBut, 0, wxLEFT | wxRIGHT, 5);
239 
240 // m_decExposureBut = new wxBitmapButton(this, ID_EXPOSURE_DECREASE,
241 // wxArtProvider::GetBitmap(wxART_GO_BACK));
242 // blendModeSizer->Add(m_decExposureBut);
243 
244  m_exposureTextCtrl = new wxTextCtrl(this, ID_EXPOSURE_TEXT, wxT("0"),
245  wxDefaultPosition,wxSize(50,-1), wxTE_PROCESS_ENTER);
246  m_exposureTextCtrl->Bind(wxEVT_TEXT_ENTER, &PreviewFrame::OnExposureTextChanged, this);
247  blendModeSizer->Add(m_exposureTextCtrl,
248  0, // not vertically strechable
249  wxLEFT | wxTOP | wxBOTTOM | wxALIGN_CENTER_VERTICAL, // draw border all around
250  5); // border width
251 // m_incExposureBut = new wxBitmapButton(this, ID_EXPOSURE_INCREASE,
252 // wxArtProvider::GetBitmap(wxART_GO_FORWARD));
253  m_exposureSpinBut = new wxSpinButton(this, ID_EXPOSURE_SPIN, wxDefaultPosition,
254  wxDefaultSize, wxSP_VERTICAL);
255  m_exposureSpinBut->SetRange(-0x8000, 0x7fff);
256  m_exposureSpinBut->SetValue(0);
257  m_exposureSpinBut->SetMaxSize(wxSize(-1, m_exposureTextCtrl->GetSize().GetHeight()));
258  m_exposureSpinBut->Bind(wxEVT_SPIN_DOWN, &PreviewFrame::OnDecreaseExposure, this);
259  m_exposureSpinBut->Bind(wxEVT_SPIN_UP, &PreviewFrame::OnIncreaseExposure, this);
260 
261  blendModeSizer->Add(m_exposureSpinBut, 0, wxALIGN_CENTER_VERTICAL);
262  blendModeSizer->Add(new wxStaticText(this, wxID_ANY, _("Range compression:")), 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5);
263  m_rangeCompressionTextCtrl = new wxTextCtrl(this, ID_RANGE_COMPRESSION_TEXT, wxT("0"),
264  wxDefaultPosition, wxSize(30, -1), wxTE_PROCESS_ENTER);
266  blendModeSizer->Add(m_rangeCompressionTextCtrl, 0, wxLEFT | wxTOP | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5);
267  m_rangeCompressionSpinBut = new wxSpinButton(this, ID_RANGE_COMPRESSION_SPIN, wxDefaultPosition, wxDefaultSize, wxSP_VERTICAL);
268  m_rangeCompressionSpinBut->SetRange(-0x8000, 0x7fff);
269  m_rangeCompressionSpinBut->SetValue(0);
270  m_rangeCompressionSpinBut->SetMaxSize(wxSize(-1, m_rangeCompressionTextCtrl->GetSize().GetHeight()));
273 
274  blendModeSizer->Add(m_rangeCompressionSpinBut, 0, wxALIGN_CENTER_VERTICAL);
275  m_topsizer->Add(blendModeSizer, 0, wxEXPAND | wxALL, 5);
276 
277  m_projParamSizer = new wxStaticBoxSizer(
278  new wxStaticBox(this, -1, _("Projection Parameters")),
279  wxHORIZONTAL);
280 
281  wxBitmapButton * resetProjButton=new wxBitmapButton(this, PROJ_PARAM_RESET_ID,
282  wxArtProvider::GetBitmap(wxART_REDO));
283  resetProjButton->SetToolTip(_("Resets the projection's parameters to their default values."));
284  resetProjButton->Bind(wxEVT_BUTTON, &PreviewFrame::OnProjParameterReset, this);
285  m_projParamSizer->Add(resetProjButton, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
286 
287  m_projParamNamesLabel.resize(PANO_PROJECTION_MAX_PARMS);
288  m_projParamTextCtrl.resize(PANO_PROJECTION_MAX_PARMS);
289  m_projParamSlider.resize(PANO_PROJECTION_MAX_PARMS);
290 
291  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++) {
292 
293  m_projParamNamesLabel[i] = new wxStaticText(this, PROJ_PARAM_NAMES_ID+i, _("param:"));
295  0, // not vertically strechable
296  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
297  5); // border width
298  m_projParamTextCtrl[i] = new wxTextCtrl(this, PROJ_PARAM_VAL_ID+i, wxT("0"),
299  wxDefaultPosition, wxSize(35,-1), wxTE_PROCESS_ENTER);
300  m_projParamTextCtrl[i]->PushEventHandler(new TextKillFocusHandler(this));
301  m_projParamTextCtrl[i]->Bind(wxEVT_TEXT_ENTER, &PreviewFrame::OnTextCtrlChanged, this);
303  0, // not vertically strechable
304  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
305  5); // border width
306 
307  m_projParamSlider[i] = new wxSlider(this, PROJ_PARAM_SLIDER_ID+i, 0, -90, 90);
309  1, // not vertically strechable
310  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
311  5); // border width
312  }
313 
314  m_topsizer->Add(m_projParamSizer, 0, wxEXPAND | wxALL, 5);
315 
316  // do not show projection param sizer
317  m_topsizer->Show(m_projParamSizer, false, true);
318 
319  wxConfigBase * config = wxConfigBase::Get();
320 
321  // add a status bar
322  CreateStatusBar(3);
323  int widths[3] = {-3, 150, 150};
324  SetStatusWidths(3, widths);
325  SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0);
326  SetStatusText(wxT(""),1);
327  SetStatusText(wxT(""),2);
328 
329  // the initial size as calculated by the sizers
330  this->SetSizer( m_topsizer );
331  m_topsizer->SetSizeHints( this );
332 
333  // set the minimize icon
334 #ifdef __WXMSW__
335  wxIconBundle myIcons(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
336  SetIcons(myIcons);
337 #else
338  wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
339  SetIcon(myIcon);
340 #endif
341 
342  m_pano.addObserver(this);
343 
344  RestoreFramePosition(this, wxT("PreviewFrame"));
345 
347 
348  long aup = config->Read(wxT("/PreviewFrame/autoUpdate"),0l);
349  m_PreviewPanel->SetAutoUpdate(aup != 0);
350 
351  m_ToolBar->ToggleTool(XRCID("preview_auto_update_tool"), aup !=0);
352 
353 #ifdef __WXMSW__
354  // wxFrame does have a strange background color on Windows..
355  this->SetBackgroundColour(m_PreviewPanel->GetBackgroundColour());
356 #endif
357 
358  if (config->Read(wxT("/PreviewFrame/isShown"), 0l) != 0) {
359  Show();
360  }
361  SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0);
362  wxAcceleratorEntry entries[3];
363 #ifdef __WXMAC
364  entries[0].Set(wxACCEL_CMD,(int)'F',ID_FULL_SCREEN);
365 #else
366  entries[0].Set(wxACCEL_NORMAL,WXK_F11,ID_FULL_SCREEN);
367 #endif
368  entries[1].Set(wxACCEL_CMD,(int)'Z',ID_UNDO);
369  entries[2].Set(wxACCEL_CMD,(int)'R',ID_REDO);
370  wxAcceleratorTable accel(3, entries);
371  SetAcceleratorTable(accel);
372  Bind(wxEVT_MENU, &PreviewFrame::OnFullScreen, this, ID_FULL_SCREEN);
373  Bind(wxEVT_MENU, &PreviewFrame::OnUndo, this, ID_UNDO);
374  Bind(wxEVT_MENU, &PreviewFrame::OnRedo, this, ID_REDO);
375 #ifdef __WXGTK__
376  // set explicit focus to button panel, otherwise the hotkey F11 is not right processed
377  m_ButtonPanel->SetFocus();
378 #endif
379  //Bind event handler
380  Bind(wxEVT_CLOSE_WINDOW, &PreviewFrame::OnClose, this);
381  Bind(wxEVT_TOOL, &PreviewFrame::OnCenterHorizontally, this, XRCID("preview_center_tool"));
382  Bind(wxEVT_TOOL, &PreviewFrame::OnFitPano, this, XRCID("preview_fit_pano_tool"));
383  Bind(wxEVT_TOOL, &PreviewFrame::OnStraighten, this, XRCID("preview_straighten_pano_tool"));
384  Bind(wxEVT_TOOL, &PreviewFrame::OnAutoPreviewToggle, this, XRCID("preview_auto_update_tool"));
385  Bind(wxEVT_TOOL, &PreviewFrame::OnUpdate, this, XRCID("preview_update_tool"));
386  Bind(wxEVT_TOOL, &PreviewFrame::OnShowAll, this, XRCID("preview_show_all_tool"));
387  Bind(wxEVT_TOOL, &PreviewFrame::OnShowNone, this, XRCID("preview_show_none_tool"));
388  Bind(wxEVT_TOOL, &PreviewFrame::OnNumTransform, this, XRCID("preview_num_transform"));
389  Bind(wxEVT_SCROLL_CHANGED, &PreviewFrame::OnChangeFOV, this);
390 }
391 
393 {
394  DEBUG_TRACE("dtor writing config");
395  wxConfigBase * config = wxConfigBase::Get();
396 
397  StoreFramePosition(this, wxT("PreviewFrame"));
398 
399  if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) {
400  config->Write(wxT("/PreviewFrame/isShown"), 1l);
401  } else {
402  config->Write(wxT("/PreviewFrame/isShown"), 0l);
403  }
404 
405  bool checked = m_ToolBar->GetToolState(XRCID("preview_auto_update_tool"));
406  config->Write(wxT("/PreviewFrame/autoUpdate"), checked ? 1l: 0l);
407  config->Write(wxT("/PreviewFrame/blendMode"), m_BlendModeChoice->GetSelection());
408  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++)
409  {
410  m_projParamTextCtrl[i]->PopEventHandler(true);
411  };
412  m_pano.removeObserver(this);
413  DEBUG_TRACE("dtor end");
414 }
415 
416 void PreviewFrame::OnChangeDisplayedImgs(wxCommandEvent & e)
417 {
418  int id = e.GetId() - ID_TOGGLE_BUT;
419  int nImg = m_pano.getNrOfImages();
420  HuginBase::UIntSet activeImages = m_pano.getActiveImages();
421  DEBUG_DEBUG("toggle_button_id: " << id << " nImg:" << nImg << " m_ToggleButtons.size(): " << m_ToggleButtons.size());
422  if (id >= 0 && id < nImg) {
423  if (e.IsChecked()) {
424  activeImages.insert(id);
425  } else {
426  activeImages.erase(id);
427  }
428 // m_PreviewPanel->SetDisplayedImages(m_displayedImgs);
430  new PanoCommand::SetActiveImagesCmd(m_pano, activeImages)
431  );
432  } else {
433  DEBUG_ERROR("invalid Togglebutton ID");
434  }
435 }
436 
438 {
439  const HuginBase::PanoramaOptions & opts = pano.getOptions();
440 
441  wxString projection;
442  m_ProjectionChoice->SetSelection(opts.getProjection());
443  m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) );
444 
445  m_outputModeChoice->SetSelection(opts.outputMode);
447  /*
448  m_exposureTextCtrl->Hide();
449  m_defaultExposureBut->Hide();
450  m_decExposureBut->Hide();
451  m_incExposureBut->Hide();
452  */
453  } else {
454  /*
455  m_exposureTextCtrl->Show();
456  m_defaultExposureBut->Show();
457  m_decExposureBut->Show();
458  m_incExposureBut->Show();
459  */
460  }
461  m_exposureTextCtrl->SetValue(wxString(hugin_utils::doubleToString(opts.outputExposureValue,2).c_str(), wxConvLocal));
462  m_rangeCompressionTextCtrl->SetValue(wxString(hugin_utils::doubleToString(opts.outputRangeCompression,1).c_str(), wxConvLocal));
463 
464  const bool activeImgs = !pano.getActiveImages().empty();
465  m_ToolBar->EnableTool(XRCID("preview_center_tool"), activeImgs);
466  m_ToolBar->EnableTool(XRCID("preview_fit_pano_tool"), activeImgs);
467  m_ToolBar->EnableTool(XRCID("preview_update_tool"), activeImgs);
468  m_ToolBar->EnableTool(XRCID("preview_num_transform"), activeImgs);
469  m_ToolBar->EnableTool(XRCID("preview_straighten_pano_tool"), pano.getNrOfImages() > 0);
470 
471  // TODO: enable display of parameters and set their limits, if projection has some.
472  int nParam = opts.m_projFeatures.numberOfParameters;
473  bool relayout = false;
474  // if the projection format has changed
475  if (opts.getProjection() != m_oldProjFormat) {
476  DEBUG_DEBUG("Projection format changed");
477  if (nParam) {
478  // show parameters and update labels.
479  m_topsizer->Show(m_projParamSizer, true, true);
480  int i;
481  for (i=0; i < nParam; i++) {
482  const pano_projection_parameter * pp = & (opts.m_projFeatures.parm[i]);
483  wxString str2(pp->name, wxConvLocal);
484  str2 = wxGetTranslation(str2);
485  m_projParamNamesLabel[i]->SetLabel(str2);
486  m_projParamSlider[i]->SetRange(hugin_utils::roundi(pp->minValue), hugin_utils::roundi(pp->maxValue));
487  }
488  for(;i < PANO_PROJECTION_MAX_PARMS; i++) {
489  m_projParamNamesLabel[i]->Hide();
490  m_projParamSlider[i]->Hide();
491  m_projParamTextCtrl[i]->Hide();
492  }
493  relayout = true;
494  } else {
495  m_topsizer->Show(m_projParamSizer, false, true);
496  relayout = true;
497  }
498  }
499  if (nParam) {
500  // display new values
501  std::vector<double> params = opts.getProjectionParameters();
502  assert((int) params.size() == nParam);
503  for (int i=0; i < nParam; i++) {
504  wxString val = wxString(hugin_utils::doubleToString(params[i],1).c_str(), wxConvLocal);
505  m_projParamTextCtrl[i]->SetValue(wxString(val.wc_str(), wxConvLocal));
506  m_projParamSlider[i]->SetValue(hugin_utils::roundi(params[i]));
507  }
508  }
509  if (relayout) {
510  m_topsizer->Layout();
511  Refresh();
512  }
513  SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0);
514  SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2);
515  m_HFOVSlider->SetValue(hugin_utils::roundi(opts.getHFOV()));
516  m_VFOVSlider->SetValue(hugin_utils::roundi(opts.getVFOV()));
517 
519  updatePano();
520 }
521 
523 {
524  DEBUG_TRACE("");
525 
526  bool dirty = false;
527 
528  unsigned int nrImages = pano.getNrOfImages();
529  unsigned int nrButtons = m_ToggleButtons.size();
530 
531 // m_displayedImgs.clear();
532 
533  // remove items for nonexisting images
534  for (int i=nrButtons-1; i>=(int)nrImages; i--)
535  {
536  m_ButtonSizer->Detach(m_ToggleButtons[i]);
537  delete m_ToggleButtons[i];
538  m_ToggleButtons.pop_back();
539  dirty = true;
540  }
541 
542  // add buttons
543  if ( nrImages >= nrButtons ) {
544  for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
545  if (*it >= nrButtons) {
546  // create new item.
547 // wxImage * bmp = new wxImage(sz.GetWidth(), sz.GetHeight());
548  wxToggleButton * but = new wxToggleButton(m_ButtonPanel,
549  ID_TOGGLE_BUT + *it,
550  wxString::Format(wxT(" %d "),*it),
551  wxDefaultPosition, wxDefaultSize,
552  wxBU_EXACTFIT);
553  but->SetValue(true);
554  but->Bind(wxEVT_TOGGLEBUTTON, &PreviewFrame::OnChangeDisplayedImgs, this);
555  m_ButtonSizer->Add(but,
556  0,
557  wxLEFT | wxTOP,
558  5);
559  m_ToggleButtons.push_back(but);
560  dirty = true;
561  }
562  }
563  }
564 
565  // update existing items
566  HuginBase::UIntSet displayedImages = m_pano.getActiveImages();
567  for (unsigned i=0; i < nrImages; i++) {
568  m_ToggleButtons[i]->SetValue(set_contains(displayedImages, i));
569  wxFileName tFilename(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
570  m_ToggleButtons[i]->SetToolTip(tFilename.GetFullName());
571  }
572 
573  if (dirty) {
574  m_ButtonSizer->FitInside(m_ButtonPanel);
575  // Layout();
576  DEBUG_INFO("New m_ButtonPanel width: " << (m_ButtonPanel->GetSize()).GetWidth());
577  DEBUG_INFO("New m_ButtonPanel Height: " << (m_ButtonPanel->GetSize()).GetHeight());
578  }
579  updatePano();
580 }
581 
582 
583 void PreviewFrame::OnClose(wxCloseEvent& event)
584 {
585  DEBUG_TRACE("OnClose")
586  // do not close, just hide if we're not forced
587  if (event.CanVeto()) {
588  event.Veto();
589  Hide();
590  DEBUG_DEBUG("hiding");
591  } else {
592  DEBUG_DEBUG("closing");
593  this->Destroy();
594  }
595 }
596 
597 void PreviewFrame::OnAutoPreviewToggle(wxCommandEvent & e)
598 {
599  m_PreviewPanel->SetAutoUpdate(e.IsChecked());
600  if (e.IsChecked()) {
602  }
603 }
604 
605 #if 0
606 // need to add the wxChoice somewhere
607 void PreviewFrame::OnProjectionChanged()
608 {
609  PanoramaOptions opt = m_pano.getOptions();
610  int lt = m_ProjectionChoice->GetSelection();
611  wxString Ip;
612  switch ( lt ) {
613  case PanoramaOptions::RECTILINEAR: Ip = _("Rectilinear"); break;
614  case PanoramaOptions::CYLINDRICAL: Ip = _("Cylindrical"); break;
615  case PanoramaOptions::EQUIRECTANGULAR: Ip = _("Equirectangular"); break;
616  }
617  opt.projectionFormat = (PanoramaOptions::ProjectionFormat) lt;
619  new PanoCommand::SetPanoOptionsCmd( pano, opt )
620  );
621  DEBUG_DEBUG ("Projection changed: " << lt << ":" << Ip )
622 
623 
624 }
625 #endif
626 
627 void PreviewFrame::OnCenterHorizontally(wxCommandEvent & e)
628 {
629  if (m_pano.getActiveImages().empty()) return;
630 
633  );
634 }
635 
636 void PreviewFrame::OnStraighten(wxCommandEvent & e)
637 {
638  if (m_pano.getNrOfImages() == 0) return;
639 
642  );
643 }
644 
645 void PreviewFrame::OnUpdate(wxCommandEvent& event)
646 {
648 }
649 
651 {
652  if (m_ToolBar->GetToolState(XRCID("preview_auto_update_tool"))) {
654  }
655 }
656 
657 void PreviewFrame::OnFitPano(wxCommandEvent & e)
658 {
659  if (m_pano.getActiveImages().empty()) return;
660 
661  DEBUG_TRACE("");
664  fitPano.run();
665  opt.setHFOV(fitPano.getResultHorizontalFOV());
667 
670  );
671 
672  DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() );
673  updatePano();
674 }
675 
676 void PreviewFrame::OnShowAll(wxCommandEvent & e)
677 {
678  if (m_pano.getNrOfImages() == 0) return;
679 
681  HuginBase::UIntSet displayedImgs;
682  for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
683  displayedImgs.insert(i);
684  }
686  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
687  );
688  updatePano();
689 }
690 
691 void PreviewFrame::OnShowNone(wxCommandEvent & e)
692 {
693  if (m_pano.getNrOfImages() == 0) return;
694 
696  for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
697  m_ToggleButtons[i]->SetValue(false);
698  }
699  HuginBase::UIntSet displayedImgs;
701  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
702  );
703  updatePano();
704 }
705 
706 void PreviewFrame::OnNumTransform(wxCommandEvent & e)
707 {
708  if (m_pano.getNrOfImages() == 0) return;
709 
710  wxDialog dlg;
711  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("dlg_numtrans"));
712  dlg.CentreOnParent();
713  if (dlg.ShowModal() == wxID_OK ) {
714  wxString text = XRCCTRL(dlg, "numtrans_yaw", wxTextCtrl)->GetValue();
715  double y;
716  if (!hugin_utils::str2double(text, y)) {
717  wxLogError(_("Yaw value must be numeric."));
718  return;
719  }
720  text = XRCCTRL(dlg, "numtrans_pitch", wxTextCtrl)->GetValue();
721  double p;
722  if (!hugin_utils::str2double(text, p)) {
723  wxLogError(_("Pitch value must be numeric."));
724  return;
725  }
726  text = XRCCTRL(dlg, "numtrans_roll", wxTextCtrl)->GetValue();
727  double r;
728  if (!hugin_utils::str2double(text, r)) {
729  wxLogError(_("Roll value must be numeric."));
730  return;
731  }
733  new PanoCommand::RotatePanoCmd(m_pano, y, p, r)
734  );
735  // update preview panel
736  updatePano();
737  } else {
738  DEBUG_DEBUG("Numerical transform canceled");
739  }
740 }
741 
742 void PreviewFrame::OnExposureTextChanged(wxCommandEvent& e)
743 {
745  const wxString text = m_exposureTextCtrl->GetValue();
746  double p = 0;
747  if (!text.IsEmpty())
748  {
749  if (!hugin_utils::str2double(text, p))
750  {
751  wxLogError(_("Value must be numeric."));
752  return;
753  }
754  opts.outputExposureValue = p;
756  // update preview panel
757  updatePano();
758  }
759 }
760 
762 {
764  const wxString text = m_rangeCompressionTextCtrl->GetValue();
765  if (text.IsEmpty())
766  {
767  return;
768  }
769  double p = 0;
770  if (!hugin_utils::str2double(text, p))
771  {
772  wxLogError(_("Value must be numeric."));
773  return;
774  }
775  if (p < 0 || p>20)
776  {
777  wxLogError(_("Value for range compression is outside of valid range."));
778  return;
779  }
780  if (p == opts.outputRangeCompression)
781  {
782  return;
783  }
784  opts.outputRangeCompression = p;
786  // update preview panel
787  updatePano();
788 }
789 
790 void PreviewFrame::OnTextCtrlChanged(wxCommandEvent & e)
791 {
793  const int nParam = opts.m_projFeatures.numberOfParameters;
794  std::vector<double> para = opts.getProjectionParameters();
795  for (int i = 0; i < nParam; i++)
796  {
797  if (e.GetEventObject() == m_projParamTextCtrl[i])
798  {
799  wxString text = m_projParamTextCtrl[i]->GetValue();
800  DEBUG_INFO("param " << i << ": = " << text.mb_str(wxConvLocal));
801  double p = 0;
802  if (!text.IsEmpty())
803  {
804  if (!hugin_utils::str2double(text, p))
805  {
806  wxLogError(_("Value must be numeric."));
807  return;
808  }
809  para[i] = p;
810  }
811  }
812  }
813  opts.setProjectionParameters(para);
815  // update preview panel
816  updatePano();
817 }
818 
819 void PreviewFrame::OnProjParameterReset(wxCommandEvent &e)
820 {
825  );
826 };
827 
828 void PreviewFrame::OnChangeFOV(wxScrollEvent & e)
829 {
830  DEBUG_TRACE("");
831 
833 
834  if (e.GetEventObject() == m_HFOVSlider) {
835  DEBUG_DEBUG("HFOV changed (slider): " << e.GetInt() << " == " << m_HFOVSlider->GetValue());
836  opt.setHFOV(e.GetInt());
837  } else if (e.GetEventObject() == m_VFOVSlider) {
838  DEBUG_DEBUG("VFOV changed (slider): " << e.GetInt());
839  opt.setVFOV(e.GetInt());
840  } else {
841  int nParam = opt.m_projFeatures.numberOfParameters;
842  std::vector<double> para = opt.getProjectionParameters();
843  for (int i = 0; i < nParam; i++) {
844  if (e.GetEventObject() == m_projParamSlider[i]) {
845  // update
846  para[i] = e.GetInt();
847  }
848  }
849  opt.setProjectionParameters(para);
850  opt.setHFOV(m_HFOVSlider->GetValue());
851  opt.setVFOV(m_VFOVSlider->GetValue());
852  }
853 
856  );
857 }
858 
859 void PreviewFrame::OnBlendChoice(wxCommandEvent & e)
860 {
861  if (e.GetEventObject() == m_BlendModeChoice) {
862  int sel = e.GetSelection();
863  switch (sel) {
864  case 0:
866  break;
867  case 1:
869  break;
870  default:
871  DEBUG_WARN("Unknown blend mode selected");
872  }
873  } else {
874  DEBUG_WARN("wxChoice event from unknown object received");
875  }
876 }
877 
878 
879 void PreviewFrame::OnDefaultExposure( wxCommandEvent & e )
880 {
881  if (m_pano.getActiveImages().size() > 0) {
886  );
887  updatePano();
888  }
889 }
890 
891 void PreviewFrame::OnIncreaseExposure( wxSpinEvent & e )
892 {
894  opt.outputExposureValue = opt.outputExposureValue + 1.0/3;
897  );
898  updatePano();
899 }
900 
901 void PreviewFrame::OnDecreaseExposure( wxSpinEvent & e )
902 {
904  opt.outputExposureValue = opt.outputExposureValue - 1.0/3;
907  );
908  updatePano();
909 }
910 
912 {
917  );
918  updatePano();
919 }
920 
922 {
927  );
928  updatePano();
929 }
930 
931 void PreviewFrame::OnProjectionChoice( wxCommandEvent & e )
932 {
933  if (e.GetEventObject() == m_ProjectionChoice) {
935  int lt = m_ProjectionChoice->GetSelection();
936  wxString Ip;
940  );
941  DEBUG_DEBUG ("Projection changed: " << lt);
942  updatePano();
943 
944  } else {
945  DEBUG_WARN("wxChoice event from unknown object received");
946  }
947 }
948 
949 void PreviewFrame::OnOutputChoice( wxCommandEvent & e)
950 {
951  if (e.GetEventObject() == m_outputModeChoice) {
953  int lt = m_outputModeChoice->GetSelection();
954  wxString Ip;
958  );
959  updatePano();
960 
961  } else {
962  DEBUG_WARN("wxChoice event from unknown object received");
963  }
964 }
965 
968 {
969  wxString msg;
970  if (!m_message.empty())
971  {
972  msg = wxGetTranslation(wxString(m_message.c_str(), wxConvLocal));
973  if (!m_filename.empty())
974  {
975  msg.Append(wxT(" "));
976  msg.Append(wxString(ProgressDisplay::m_filename.c_str(), HUGIN_CONV_FILENAME));
977  };
978  };
979  GetStatusBar()->SetStatusText(msg, 0);
980 
981 #ifdef __WXMSW__
982  UpdateWindow(NULL);
983 #endif
984 }
985 
986 void PreviewFrame::OnFullScreen(wxCommandEvent & e)
987 {
988  ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
989 #ifdef __WXGTK__
990  //workaround a wxGTK bug that also the toolbar is hidden, but not requested to hide
991  GetToolBar()->Show(true);
992 #endif
994 };
995 
996 void PreviewFrame::OnUndo(wxCommandEvent &e)
997 {
999  {
1000  wxCommandEvent dummy(wxEVT_COMMAND_MENU_SELECTED, XRCID("ID_EDITUNDO"));
1001  m_parent->GetEventHandler()->AddPendingEvent(dummy);
1002  }
1003  else
1004  {
1005  wxBell();
1006  };
1007 };
1008 
1009 void PreviewFrame::OnRedo(wxCommandEvent &e)
1010 {
1012  {
1013  wxCommandEvent dummy(wxEVT_COMMAND_MENU_SELECTED, XRCID("ID_EDITREDO"));
1014  m_parent->GetEventHandler()->AddPendingEvent(dummy);
1015  }
1016  else
1017  {
1018  wxBell();
1019  };
1020 };
1021 
#define DEBUG_INFO(msg)
Definition: utils.h:69
void OnShowAll(wxCommandEvent &e)
HuginBase::Panorama & m_pano
Definition: PreviewFrame.h:95
PanoramaOptions::ProjectionFormat getProjection() const
void OnUpdate(wxCommandEvent &event)
implementation of huginApp Class
wxBoxSizer * m_topsizer
Definition: PreviewFrame.h:120
wxString m_choices[3]
Definition: PreviewFrame.h:110
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxT("panel"))
#define PF_STYLE
void setHeight(unsigned int h)
set panorama height
pano_projection_features m_projFeatures
int roundi(T x)
Definition: hugin_math.h:73
static double calcMeanExposure(const PanoramaData &pano)
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
void OnBlendChoice(wxCommandEvent &e)
wxSlider * m_VFOVSlider
Definition: PreviewFrame.h:100
center panorama horizontically
Definition: PanoCommand.h:250
void OnNumTransform(wxCommandEvent &e)
void OnTextCtrlChanged(wxCommandEvent &e)
std::vector< wxStaticText * > m_projParamNamesLabel
Definition: PreviewFrame.h:122
bool fovCalcSupported(ProjectionFormat f) const
true, if FOV calcuations are supported for projection f
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
virtual ~PreviewFrame()
dtor.
wxSpinButton * m_exposureSpinBut
Definition: PreviewFrame.h:106
#define DEBUG_TRACE(msg)
Definition: utils.h:67
unsigned int getHeight() const
get panorama height
std::vector< wxSlider * > m_projParamSlider
Definition: PreviewFrame.h:124
wxChoice * m_ProjectionChoice
Definition: PreviewFrame.h:102
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
void setProjectionParameters(const std::vector< double > &params)
set the optional parameters (they need to be of the correct size)
include file for the hugin project
virtual void run()
runs the algorithm.
wxToolBar * m_ToolBar
Definition: PreviewFrame.h:98
void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
notifies about changes to images
void OnRangeCompressionTextChanged(wxCommandEvent &e)
std::string doubleToString(double d, int digits)
convert a double to a string, suitable for display within a GUI.
Definition: utils.cpp:228
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition: huginApp.cpp:646
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
void OnCenterHorizontally(wxCommandEvent &e)
set the panorama options
Definition: PanoCommand.h:418
#define DEBUG_WARN(msg)
Definition: utils.h:74
void OnIncreaseExposure(wxSpinEvent &e)
void Init(PreviewFrame *parent, HuginBase::Panorama *pano)
Model for a panorama.
Definition: Panorama.h:152
void OnUndo(wxCommandEvent &e)
event handler for undo
void resetProjectionParameters()
sets the optional parameters to their default values
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
void SetAutoUpdate(bool enabled)
wxSlider * m_HFOVSlider
Definition: PreviewFrame.h:99
void OnRedo(wxCommandEvent &e)
event handler for redo
virtual double getResultHeight()
Definition: FitPanorama.h:75
void OnExposureTextChanged(wxCommandEvent &e)
void OnProjectionChoice(wxCommandEvent &e)
void SetBlendMode(BlendMode b)
void OnShowNone(wxCommandEvent &e)
wxBitmapButton * m_defaultExposureBut
Definition: PreviewFrame.h:105
std::vector< wxToggleButton * > m_ToggleButtons
Definition: PreviewFrame.h:125
static GlobalCmdHist & getInstance()
std::vector< wxTextCtrl * > m_projParamTextCtrl
Definition: PreviewFrame.h:123
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Store window size and position in configfile/registry.
Definition: wxutils.cpp:133
void OnChangeFOV(wxScrollEvent &e)
wxBoxSizer * m_ButtonSizer
Definition: PreviewFrame.h:117
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
Contains functions to transform whole images.
#define DEBUG_ERROR(msg)
Definition: utils.h:76
wxScrolledWindow * m_ButtonPanel
Definition: PreviewFrame.h:116
void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
straighten panorama horizontically
Definition: PanoCommand.h:259
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
void OnStraighten(wxCommandEvent &e)
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
include file for the hugin project
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
virtual double getResultHorizontalFOV()
Definition: FitPanorama.h:68
void OnClose(wxCloseEvent &e)
PreviewFrame(wxFrame *frame, HuginBase::Panorama &pano)
ctor.
void OnChangeDisplayedImgs(wxCommandEvent &e)
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
static T max(T x, T y)
Definition: svm.cpp:65
wxSpinButton * m_rangeCompressionSpinBut
Definition: PreviewFrame.h:108
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
void OnFitPano(wxCommandEvent &e)
void OnProjParameterReset(wxCommandEvent &e)
event handler for reset projection parameters
platform/compiler specific stuff.
void OnOutputChoice(wxCommandEvent &e)
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
wxStaticBoxSizer * m_projParamSizer
Definition: PreviewFrame.h:121
void OnRangeCompressionIncrease(wxSpinEvent &e)
void OnRangeCompressionDecrease(wxSpinEvent &e)
A preview panel that renders the pictures using the panotools library.
Definition: PreviewPanel.h:40
void ForceUpdate()
void OnDefaultExposure(wxCommandEvent &e)
PreviewPanel * m_PreviewPanel
Definition: PreviewFrame.h:97
ProjectionFormat
Projection of final panorama.
wxTextCtrl * m_exposureTextCtrl
Definition: PreviewFrame.h:104
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
Panorama image options.
wxStaticBoxSizer * m_ToggleButtonSizer
Definition: PreviewFrame.h:118
void OnAutoPreviewToggle(wxCommandEvent &e)
Rotate the panorama.
Definition: PanoCommand.h:448
wxTextCtrl * m_rangeCompressionTextCtrl
Definition: PreviewFrame.h:107
static T min(T x, T y)
Definition: svm.cpp:62
void updateProgressDisplay()
update the display
void OnDecreaseExposure(wxSpinEvent &e)
wxChoice * m_BlendModeChoice
Definition: PreviewFrame.h:101
void OnFullScreen(wxCommandEvent &e)
event handler for full screen
wxChoice * m_outputModeChoice
Definition: PreviewFrame.h:103
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Restore window size and position from configfile/registry.
Definition: wxutils.cpp:65