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 BEGIN_EVENT_TABLE(CPImagesComboBox,wxOwnerDrawnComboBox)
37  EVT_MOUSEWHEEL(CPImagesComboBox::OnMouseWheel)
38  EVT_KEY_DOWN(CPImagesComboBox::OnKeyDown)
40 
41 void CPImagesComboBox::OnMouseWheel(wxMouseEvent & e)
42 {
43  //mimic wxChoice behaviour
44  //when popup is shown, there could be a scrollbar which processes the mouse wheel event
45  if(!IsPopupShown())
46  {
47  if(e.GetWheelRotation()<0)
48  SelectNext();
49  else
50  SelectPrev();
51  }
52  else
53  {
54  e.Skip();
55  };
56 };
57 
58 void CPImagesComboBox::OnKeyDown(wxKeyEvent & e)
59 {
60  if(!IsPopupShown())
61  {
62  //mimic wxChoice behaviour
63  switch (e.GetKeyCode()){
64  case WXK_DOWN:
65  case WXK_RIGHT:
66  case WXK_NUMPAD_DOWN:
67  case WXK_NUMPAD_RIGHT:
68  SelectNext();
69  break;
70  case WXK_UP:
71  case WXK_LEFT:
72  case WXK_NUMPAD_UP:
73  case WXK_NUMPAD_LEFT:
74  SelectPrev();
75  break;
76  case WXK_PAGEDOWN:
77  case WXK_NUMPAD_PAGEDOWN:
78  SelectNext(5);
79  break;
80  case WXK_PAGEUP:
81  case WXK_NUMPAD_PAGEUP:
82  SelectPrev(5);
83  break;
84  case WXK_HOME:
85  case WXK_NUMPAD_HOME:
86  SelectPrev(GetCount());
87  break;
88  case WXK_END:
89  case WXK_NUMPAD_END:
90  SelectNext(GetCount());
91  break;
92  case WXK_SPACE:
93  ShowPopup();
94  break;
95  default:
96  e.Skip();
97  };
98  }
99  else
100  {
101  e.Skip();
102  }
103 };
104 
106 {
107  int index=std::min<int>(GetSelection()+step,GetCount()-1);
108  if(index!=GetSelection())
109  {
110  Select(index);
111  Update();
112  NotifyParent();
113  };
114 };
115 
117 {
118  int index=std::max<int>(GetSelection()-step,0);
119  if(index!=GetSelection())
120  {
121  Select(index);
122  Update();
123  NotifyParent();
124  };
125 };
126 
128 {
129  //notify parent about changed selection
130  //select doesn't send the corresponding event
131  wxCommandEvent ne(wxEVT_COMMAND_COMBOBOX_SELECTED);
132  ne.SetEventObject(this);
133  ne.SetId(this->GetId());
134  ne.SetInt(GetSelection());
135  ProcessEvent(ne);
136 };
137 
139 {
140  CPConnection.resize(0);
141  refImage=0;
142 };
143 
145  const wxRect& rect,
146  int item,
147  int WXUNUSED(flags)) const
148 {
149  if ( item == wxNOT_FOUND )
150  return;
151 
152  wxCoord w, h;
153  GetTextExtent(GetString(item), &w, &h);
154  wxCoord maxWidth=0.73*rect.width-3;
155 
156  // 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>
157 
158  // if image connected by control points, add number of CPs to width equation as well
159  wxCoord qty_w = 0;
160  wxString qty_cp = wxT("");
161  if(CPConnection[item]>-1.0)
162  {
163  qty_cp = wxString::Format(wxT(" %d"), CPCount[item]);
164  GetTextExtent(qty_cp, &qty_w, &h);
165  }
166 
167  // determine if the string can fit inside the current combo box
168  if (w +qty_w <= maxWidth)
169  {
170  // it can, draw it
171  dc.DrawText(GetString(item),rect.x + 3,rect.y + ((rect.height - dc.GetCharHeight())/2));
172 
173  }
174  else // otherwise, truncate and add an ellipsis
175  {
176  // determine the base width
177  wxString ellipsis(wxT("..."));
178  wxCoord base_w;
179  GetTextExtent(ellipsis, &base_w, &h);
180 
181  // continue until we have enough space or only one character left
182  wxString drawntext = GetString(item);
183  while (drawntext.length() > 1)
184  {
185  drawntext.RemoveLast();
186  GetTextExtent(drawntext,&w,&h);
187  if (w + base_w + qty_w <= maxWidth)
188  break;
189  }
190 
191  // now draw the text
192  dc.DrawText(drawntext, rect.x + 3, rect.y + ((rect.height - dc.GetCharHeight())/2));
193  dc.DrawText(ellipsis, rect.x + 3 + w, rect.y + ((rect.height - dc.GetCharHeight())/2));
194  }
195 
196  // draw rectangle when images are connected by control points
197  if(CPConnection[item]>-1.0)
198  {
199  wxCoord x;
200  x=rect.width / 5 *(1-std::min<double>(CPConnection[item],10)/10);
201  //ensure that always a bar is drawn
202  x=std::max<wxCoord>(5,x);
203  const wxPen * oldPen = & dc.GetPen();
204  const wxBrush * oldBrush= & dc.GetBrush();
205  //inner rectangle with color proportional to max cp error (max. 10)
206  wxPen MyPen(wxColour(255, 0, 0), 1, wxPENSTYLE_SOLID);
207  wxBrush MyBrush(wxColour(255,0,0), wxBRUSHSTYLE_SOLID);
208  double red, green, blue;
209 
210  hugin_utils::ControlPointErrorColour(CPConnection[item],red,green,blue);
211 
212  //Scale colour to 0-255
213  red *= 255;
214  green *= 255;
215 
216  MyPen.SetColour(wxColour(red,green,0));
217  MyBrush.SetColour(wxColour(red,green,0));
218  dc.SetPen(MyPen);
219  dc.SetBrush(MyBrush);
220  dc.DrawRectangle(rect.x+0.75*rect.width,rect.y+rect.height/6+1,x,2*rect.height/3);
221 /*
222  // half the rectangle
223  int half=rect.width/10;
224  // color steps
225  double step_red=255.0/half;
226  double step_green=192.0/half;
227  // starting color
228  double red=255.0;
229  double green=0.0;
230  for(int i=0;i<x;i++)
231  {
232  MyPen.SetColour(wxColour(red,green,0));
233  MyBrush.SetColour(wxColour(red,green,0));
234  dc.SetPen(MyPen);
235  dc.SetBrush(MyBrush);
236  dc.DrawRectangle(rect.x+0.75*rect.width+i,rect.y+rect.height/6+1,1,2*rect.height/3);
237  // gradient calculation
238  if(i<half)
239  {
240  // until half-way increase the green
241  green=green+step_green;
242  }
243  else
244  {
245  // after half-way decrease the red
246  red=red-step_red;
247  }
248  }
249 */
250  //outer rectangle, same colour as text
251  MyPen.SetColour(dc.GetTextForeground());
252  dc.SetPen(MyPen);
253  dc.SetBrush(*wxTRANSPARENT_BRUSH);
254  dc.DrawRectangle(rect.x+0.75*rect.width,rect.y+rect.height/6+1,rect.width/5,2*rect.height/3);
255  dc.SetPen(*oldPen);
256  dc.SetBrush(*oldBrush);
257 
258  // draw number of connecting CPs
259  dc.DrawText(qty_cp, rect.x - 3 - qty_w +0.75*rect.width , rect.y + ((rect.height - dc.GetCharHeight())/2));
260 
261  };
262 };
263 
265 {
266  CPConnection.clear();
267  CPCount.clear();
268  CPConnection.resize(this->GetCount(),-1.0);
269  CPCount.resize(this->GetCount(),0);
270  unsigned int noPts = pano->getNrOfCtrlPoints();
271  // loop over all points to get the maximum error and to count the number of CPs
272  for (unsigned int ptIdx = 0 ; ptIdx < noPts ; ptIdx++)
273  {
274  const HuginBase::ControlPoint & cp = pano->getCtrlPoint(ptIdx);
275  if(cp.image1Nr==refImage)
276  {
277  CPConnection[cp.image2Nr]=std::max<double>(cp.error,CPConnection[cp.image2Nr]);
278  CPCount[cp.image2Nr]++;
279  }
280  else if(cp.image2Nr==refImage)
281  {
282  CPConnection[cp.image1Nr]=std::max<double>(cp.error,CPConnection[cp.image1Nr]);
283  CPCount[cp.image1Nr]++;
284  };
285  }
286 };
287 
288 IMPLEMENT_DYNAMIC_CLASS(CPImagesComboBox, wxOwnerDrawnComboBox)
289 
290 IMPLEMENT_DYNAMIC_CLASS(CPImagesComboBoxXmlHandler, wxOwnerDrawnComboBoxXmlHandler)
291 
292 CPImagesComboBoxXmlHandler::CPImagesComboBoxXmlHandler()
293  : wxOwnerDrawnComboBoxXmlHandler()
294 {
295  AddWindowStyles();
296 }
297 
299 {
300  XRC_MAKE_INSTANCE(cp, CPImagesComboBox)
301 
302  cp->Create(m_parentAsWindow,
303  GetID(), wxEmptyString,
304  GetPosition(), GetSize(),
305  GetStyle(wxT("style")), wxDefaultValidator,
306  GetName());
307 
308  SetupWindow(cp);
309 
310  return cp;
311 }
312 
314 {
315  return IsOfClass(node, wxT("CPImagesComboBox"));
316 }
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
END_EVENT_TABLE()
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
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
static uint16_t flags
std::vector< unsigned int > CPCount
unsigned int refImage
void SelectNext(int step=1)