Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CPImagesComboBox.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
13 /* This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This software is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public
24  * License along with this software. If not, see
25  * <http://www.gnu.org/licenses/>.
26  *
27  */
28 
29 #ifdef _WIN32
30 #include "wx/msw/wrapwin.h"
31  // Mingw define still DIFFERENCE, which conflicts with vigra, so disable it
32 #undef DIFFERENCE
33 #endif
34 #include "hugin/CPImagesComboBox.h"
35 
36 bool CPImagesComboBox::Create(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size,
37  long style, const wxValidator& validator, const wxString& name)
38 {
39  if (!wxOwnerDrawnComboBox::Create(parent, id, value, pos, size, wxArrayString(), style, validator, name))
40  {
41  return false;
42  }
43  Bind(wxEVT_MOUSEWHEEL, &CPImagesComboBox::OnMouseWheel, this);
44  Bind(wxEVT_KEY_DOWN, &CPImagesComboBox::OnKeyDown, this);
45  return true;
46 }
47 
48 void CPImagesComboBox::OnMouseWheel(wxMouseEvent & e)
49 {
50  //mimic wxChoice behaviour
51  //when popup is shown, there could be a scrollbar which processes the mouse wheel event
52  if(!IsPopupShown())
53  {
54  if(e.GetWheelRotation()<0)
55  SelectNext();
56  else
57  SelectPrev();
58  }
59  else
60  {
61  e.Skip();
62  };
63 };
64 
65 void CPImagesComboBox::OnKeyDown(wxKeyEvent & e)
66 {
67  if(!IsPopupShown())
68  {
69  //mimic wxChoice behaviour
70  switch (e.GetKeyCode()){
71  case WXK_DOWN:
72  case WXK_RIGHT:
73  case WXK_NUMPAD_DOWN:
74  case WXK_NUMPAD_RIGHT:
75  SelectNext();
76  break;
77  case WXK_UP:
78  case WXK_LEFT:
79  case WXK_NUMPAD_UP:
80  case WXK_NUMPAD_LEFT:
81  SelectPrev();
82  break;
83  case WXK_PAGEDOWN:
84  case WXK_NUMPAD_PAGEDOWN:
85  SelectNext(5);
86  break;
87  case WXK_PAGEUP:
88  case WXK_NUMPAD_PAGEUP:
89  SelectPrev(5);
90  break;
91  case WXK_HOME:
92  case WXK_NUMPAD_HOME:
93  SelectPrev(GetCount());
94  break;
95  case WXK_END:
96  case WXK_NUMPAD_END:
97  SelectNext(GetCount());
98  break;
99  case WXK_SPACE:
100  ShowPopup();
101  break;
102  default:
103  e.Skip();
104  };
105  }
106  else
107  {
108  e.Skip();
109  }
110 };
111 
113 {
114  int index=std::min<int>(GetSelection()+step,GetCount()-1);
115  if(index!=GetSelection())
116  {
117  Select(index);
118  Update();
119  NotifyParent();
120  };
121 };
122 
124 {
125  int index=std::max<int>(GetSelection()-step,0);
126  if(index!=GetSelection())
127  {
128  Select(index);
129  Update();
130  NotifyParent();
131  };
132 };
133 
135 {
136  //notify parent about changed selection
137  //select doesn't send the corresponding event
138  wxCommandEvent ne(wxEVT_COMMAND_COMBOBOX_SELECTED);
139  ne.SetEventObject(this);
140  ne.SetId(this->GetId());
141  ne.SetInt(GetSelection());
142  ProcessEvent(ne);
143 };
144 
146 {
147  CPConnection.resize(0);
148  refImage=0;
149 };
150 
152  const wxRect& rect,
153  int item,
154  int WXUNUSED(flags)) const
155 {
156  if ( item == wxNOT_FOUND )
157  return;
158 
159  wxCoord w, h;
160  GetTextExtent(GetString(item), &w, &h);
161  wxCoord maxWidth=0.73*rect.width-3;
162 
163  // TODO: note that since wxWidgets 2.9.0 you should not use wxT anymore <http://docs.wxwidgets.org/trunk/group__group__funcmacro__string.html#g437ea6ba615b75dac8603e96ec864160>
164 
165  // if image connected by control points, add number of CPs to width equation as well
166  wxCoord qty_w = 0;
167  wxString qty_cp = wxT("");
168  if(CPConnection[item]>-1.0)
169  {
170  qty_cp = wxString::Format(wxT(" %d"), CPCount[item]);
171  GetTextExtent(qty_cp, &qty_w, &h);
172  }
173 
174  // determine if the string can fit inside the current combo box
175  if (w +qty_w <= maxWidth)
176  {
177  // it can, draw it
178  dc.DrawText(GetString(item),rect.x + 3,rect.y + ((rect.height - dc.GetCharHeight())/2));
179 
180  }
181  else // otherwise, truncate and add an ellipsis
182  {
183  // determine the base width
184  wxString ellipsis(wxT("..."));
185  wxCoord base_w;
186  GetTextExtent(ellipsis, &base_w, &h);
187 
188  // continue until we have enough space or only one character left
189  wxString drawntext = GetString(item);
190  while (drawntext.length() > 1)
191  {
192  drawntext.RemoveLast();
193  GetTextExtent(drawntext,&w,&h);
194  if (w + base_w + qty_w <= maxWidth)
195  break;
196  }
197 
198  // now draw the text
199  dc.DrawText(drawntext, rect.x + 3, rect.y + ((rect.height - dc.GetCharHeight())/2));
200  dc.DrawText(ellipsis, rect.x + 3 + w, rect.y + ((rect.height - dc.GetCharHeight())/2));
201  }
202 
203  // draw rectangle when images are connected by control points
204  if(CPConnection[item]>-1.0)
205  {
206  wxCoord x;
207  x=rect.width / 5 *(1-std::min<double>(CPConnection[item],10)/10);
208  //ensure that always a bar is drawn
209  x=std::max<wxCoord>(5,x);
210  const wxPen * oldPen = & dc.GetPen();
211  const wxBrush * oldBrush= & dc.GetBrush();
212  //inner rectangle with color proportional to max cp error (max. 10)
213  wxPen MyPen(wxColour(255, 0, 0), 1, wxPENSTYLE_SOLID);
214  wxBrush MyBrush(wxColour(255,0,0), wxBRUSHSTYLE_SOLID);
215  double red, green, blue;
216 
217  hugin_utils::ControlPointErrorColour(CPConnection[item],red,green,blue);
218 
219  //Scale colour to 0-255
220  red *= 255;
221  green *= 255;
222 
223  MyPen.SetColour(wxColour(red,green,0));
224  MyBrush.SetColour(wxColour(red,green,0));
225  dc.SetPen(MyPen);
226  dc.SetBrush(MyBrush);
227  dc.DrawRectangle(rect.x+0.75*rect.width,rect.y+rect.height/6+1,x,2*rect.height/3);
228 /*
229  // half the rectangle
230  int half=rect.width/10;
231  // color steps
232  double step_red=255.0/half;
233  double step_green=192.0/half;
234  // starting color
235  double red=255.0;
236  double green=0.0;
237  for(int i=0;i<x;i++)
238  {
239  MyPen.SetColour(wxColour(red,green,0));
240  MyBrush.SetColour(wxColour(red,green,0));
241  dc.SetPen(MyPen);
242  dc.SetBrush(MyBrush);
243  dc.DrawRectangle(rect.x+0.75*rect.width+i,rect.y+rect.height/6+1,1,2*rect.height/3);
244  // gradient calculation
245  if(i<half)
246  {
247  // until half-way increase the green
248  green=green+step_green;
249  }
250  else
251  {
252  // after half-way decrease the red
253  red=red-step_red;
254  }
255  }
256 */
257  //outer rectangle, same colour as text
258  MyPen.SetColour(dc.GetTextForeground());
259  dc.SetPen(MyPen);
260  dc.SetBrush(*wxTRANSPARENT_BRUSH);
261  dc.DrawRectangle(rect.x+0.75*rect.width,rect.y+rect.height/6+1,rect.width/5,2*rect.height/3);
262  dc.SetPen(*oldPen);
263  dc.SetBrush(*oldBrush);
264 
265  // draw number of connecting CPs
266  dc.DrawText(qty_cp, rect.x - 3 - qty_w +0.75*rect.width , rect.y + ((rect.height - dc.GetCharHeight())/2));
267 
268  };
269 };
270 
272 {
273  CPConnection.clear();
274  CPCount.clear();
275  CPConnection.resize(this->GetCount(),-1.0);
276  CPCount.resize(this->GetCount(),0);
277  unsigned int noPts = pano->getNrOfCtrlPoints();
278  // loop over all points to get the maximum error and to count the number of CPs
279  for (unsigned int ptIdx = 0 ; ptIdx < noPts ; ptIdx++)
280  {
281  const HuginBase::ControlPoint & cp = pano->getCtrlPoint(ptIdx);
282  if(cp.image1Nr==refImage)
283  {
284  CPConnection[cp.image2Nr]=std::max<double>(cp.error,CPConnection[cp.image2Nr]);
285  CPCount[cp.image2Nr]++;
286  }
287  else if(cp.image2Nr==refImage)
288  {
289  CPConnection[cp.image1Nr]=std::max<double>(cp.error,CPConnection[cp.image1Nr]);
290  CPCount[cp.image1Nr]++;
291  };
292  }
293 };
294 
295 IMPLEMENT_DYNAMIC_CLASS(CPImagesComboBox, wxOwnerDrawnComboBox)
296 
297 IMPLEMENT_DYNAMIC_CLASS(CPImagesComboBoxXmlHandler, wxOwnerDrawnComboBoxXmlHandler)
298 
299 CPImagesComboBoxXmlHandler::CPImagesComboBoxXmlHandler()
300  : wxOwnerDrawnComboBoxXmlHandler()
301 {
302  AddWindowStyles();
303 }
304 
306 {
307  XRC_MAKE_INSTANCE(cp, CPImagesComboBox)
308 
309  cp->Create(m_parentAsWindow,
310  GetID(), wxEmptyString,
311  GetPosition(), GetSize(),
312  GetStyle(wxT("style")), wxDefaultValidator,
313  GetName());
314 
315  SetupWindow(cp);
316 
317  return cp;
318 }
319 
321 {
322  return IsOfClass(node, wxT("CPImagesComboBox"));
323 }
void CalcCPDistance(HuginBase::Panorama *pano)
Get maximum CP distance for all images pairs containing the reference image.
void SelectPrev(int step=1)
std::vector< double > CPConnection
void OnKeyDown(wxKeyEvent &e)
Key handler to mimic wxChoice behavior.
Definition of CPImagesComboBox and CPImagesComboBoxXmlHandler class.
std::size_t getNrOfCtrlPoints() const
number of control points
Definition: Panorama.h:306
Owner Drawn ComboBox for showing connected images on CP tab.
represents a control point
Definition: ControlPoint.h:38
virtual void OnDrawItem(wxDC &dc, const wxRect &rect, int item, int WXUNUSED(flags)) const
Paint method for drawing text and indication bar of combo box.
Model for a panorama.
Definition: Panorama.h:152
virtual bool CanHandle(wxXmlNode *node)
Internal use to identify right xml handler.
const ControlPoint & getCtrlPoint(std::size_t nr) const
get a control point, counting starts with 0
Definition: Panorama.h:312
void OnMouseWheel(wxMouseEvent &e)
Mouse wheel handler to mimic wxChoice behavior.
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
virtual wxObject * DoCreateResource()
Create CPImagesComboBox from resource.
IMPEX double h[25][1024]
Definition: emor.cpp:169
xrc handler for CPImagesComboBox
void ControlPointErrorColour(const double cperr, double &r, double &g, double &b)
Definition: utils.cpp:341
bool Create(wxWindow *parent, wxWindowID id, const wxString &value, const wxPoint &pos, const wxSize &size, long style=0, const wxValidator &validator=wxDefaultValidator, const wxString &name=wxASCII_STR(wxComboBoxNameStr))
create control, bind events
static uint16_t flags
std::vector< unsigned int > CPCount
unsigned int refImage
void SelectNext(int step=1)