00001 #include <wx/settings.h>
00002 #include <wx/textctrl.h>
00003 #include <wx/colordlg.h>
00004
00005 #include "trafu_ctrl_event.h"
00006 #include "trafu_ctrl.h"
00007
00008 BEGIN_EVENT_TABLE(TransferFunctionCtrlCanvas, wxControl)
00009 EVT_PAINT(TransferFunctionCtrlCanvas::OnPaint)
00010 EVT_MOUSE_EVENTS(TransferFunctionCtrlCanvas::OnMouseEvent)
00011 EVT_SIZE(TransferFunctionCtrlCanvas::OnSize)
00012 END_EVENT_TABLE()
00013
00014 IMPLEMENT_DYNAMIC_CLASS(TransferFunctionCtrlCanvas, wxControl)
00015
00016 void TransferFunctionCtrlCanvas::OnSize(wxSizeEvent& event)
00017 {
00018 }
00019
00020 bool TransferFunctionCtrlCanvas::Create(wxWindow* parent,
00021 wxWindowID id,
00022 const wxPoint& pos,
00023 const wxSize& size,
00024 long style)
00025 {
00026 if (!wxControl::Create(parent, id, pos, size, style))
00027 return false;
00028
00029 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
00030
00031 SetInitialSize(size);
00032
00033 return true;
00034 }
00035
00036 void TransferFunctionCtrlCanvas::SetHistogramData(const HistogramData *histogramdata)
00037 {
00038 m_hist_data = histogramdata;
00039 }
00040
00041 void TransferFunctionCtrlCanvas::Init()
00042 {
00043 m_button_radius = 4;
00044
00045 m_points = 0;
00046
00047 m_colour_range_height = 35;
00048 }
00049
00050 void TransferFunctionCtrlCanvas::SetTraFuDataPointer(TraFuData *data)
00051 {
00052 m_points = data;
00053 m_active_point = m_points->end();
00054 }
00055
00056 void TransferFunctionCtrlCanvas::OnPaint(wxPaintEvent& event)
00057 {
00058 wxBufferedPaintDC dc(this);
00059
00060 dc.Clear();
00061
00062 DrawHist(&dc);
00063
00064 m_points->Sort();
00065
00066 Mapping_point_iterator_t last_point;
00067 Mapping_point_iterator_t iterPoint = last_point = m_points->begin();
00068
00069 dc.SetPen(wxPen(wxColour(0, 0, 0), 1, wxSOLID));
00070
00071 for (++iterPoint;
00072 iterPoint != m_points->end();
00073 iterPoint++)
00074 {
00075 dc.DrawLine(GetPosition(last_point), GetPosition(iterPoint));
00076 last_point = iterPoint;
00077 }
00078
00079 --iterPoint;
00080 dc.DrawLine(GetPosition(last_point), GetPosition(iterPoint));
00081
00082 DrawPoints(&dc);
00083
00084 if(m_active_point != m_points->end())
00085 {
00086 dc.SetPen(wxPen(*wxLIGHT_GREY_PEN));
00087 dc.DrawLine(GetPosition(m_active_point).x,
00088 0,
00089 GetPosition(m_active_point).x,
00090 GetSize().GetHeight());
00091 dc.DrawLine(0,
00092 GetPosition(m_active_point).y,
00093 GetSize().GetWidth(),
00094 GetPosition(m_active_point).y);
00095 }
00096
00097 DrawRange(&dc);
00098 }
00099
00100 void TransferFunctionCtrlCanvas::DrawPoints(wxDC *dc)
00101 {
00102 wxBrush old_brush = dc->GetBrush();
00103 wxPen old_pen = dc->GetPen();
00104
00105 dc->SetPen(wxPen(*wxBLACK));
00106
00107 for (Mapping_point_iterator_t iterPoint = m_points->begin();
00108 iterPoint != m_points->end();
00109 iterPoint++)
00110 {
00111 dc->SetBrush(wxBrush(GetColour(*iterPoint)));
00112 dc->DrawRectangle(GetPosition(iterPoint) - wxPoint(5, 5), wxSize(10, 10));
00113 }
00114
00115 dc->SetBrush(old_brush);
00116 dc->SetPen(old_pen);
00117 }
00118
00119 void TransferFunctionCtrlCanvas::DrawHist(wxDC *dc)
00120 {
00121
00122 if (!m_hist_data) return;
00123
00124 const int width = GetCanvasWidth();
00125 const unsigned height = GetCanvasHeight();
00126
00127 const std::vector<float> hist_lines = m_hist_data->ResampleData(width);
00128 const float max_value = *std::max_element(hist_lines.begin(), hist_lines.end());
00129 const float scale_factor = height / max_value;
00130
00131 const wxPen old_pen = dc->GetPen();
00132
00133 dc->SetPen(wxPen(wxColour(150, 150, 150), 1, wxSOLID));
00134
00135 for (int x = 0; x < width; ++x)
00136 dc->DrawLine(x, height - hist_lines[x] * scale_factor, x, height);
00137
00138 dc->SetPen(old_pen);
00139 }
00140
00141 void TransferFunctionCtrlCanvas::DrawRange(wxDC *dc)
00142 {
00143 int range_start = GetSize().GetHeight() - m_colour_range_height;
00144 int range_end = range_start + m_colour_range_height;
00145 int canvas_width = GetCanvasWidth();
00146
00147 Mapping_point_vector_t colors = m_points->createDensityVector(canvas_width);
00148
00149 wxPen old_pen = dc->GetPen();
00150
00151 for(int i = 0; i < canvas_width; i++)
00152 {
00153 dc->SetPen(wxPen(colors[i].m_colour.wx()));
00154 dc->DrawLine(i, range_start, i, range_end);
00155 }
00156
00157 dc->SetPen(old_pen);
00158 }
00159
00160 bool TransferFunctionCtrlCanvas::PointContains(Mapping_point_iterator_t point, const wxPoint &pos)
00161 {
00162 wxPoint center = GetPosition(point);
00163 wxPoint margin(5, 5);
00164
00165 return wxRect(center - margin, center + margin).Contains(pos);
00166 }
00167
00168 Mapping_point_iterator_t TransferFunctionCtrlCanvas::GetHitPoint(const wxPoint &pos)
00169 {
00170 for (Mapping_point_iterator_t iterPoint = m_points->begin(); iterPoint != m_points->end(); iterPoint++)
00171 if (PointContains(iterPoint, pos)) return iterPoint;
00172
00173 return m_points->end();
00174 }
00175
00176 void TransferFunctionCtrlCanvas::OnMouseEvent(wxMouseEvent& event)
00177 {
00178
00179 try
00180 {
00181 if (event.GetPosition().y <= GetCanvasHeight()) {
00182 if (m_active_point != m_points->end()) SetPointPosition(m_active_point, event.GetPosition());
00183
00184 if (event.ButtonDClick(wxMOUSE_BTN_LEFT)) {
00185 Mapping_point_iterator_t hit_point = GetHitPoint(event.GetPosition());
00186 if (hit_point != m_points->end()) {
00187 SetMoving(m_active_point, false);
00188
00189 wxColourDialog colour_dlg(this);
00190
00191 if (wxID_OK == colour_dlg.ShowModal()) {
00192 SetColour(*hit_point, colour_dlg.GetColourData().GetColour());
00193 NotifyChange();
00194 }
00195 } else AddNewPoint(event.GetPosition());
00196
00197 } else {
00198 if (event.ButtonDown(wxMOUSE_BTN_RIGHT)) {
00199 Mapping_point_iterator_t hit_point = GetHitPoint(event.GetPosition());
00200 if (hit_point != m_points->end() && hit_point != m_active_point) {
00201 DeletePoint(hit_point);
00202 NotifyChange();
00203 }
00204 }
00205
00206 if (event.ButtonUp(wxMOUSE_BTN_LEFT)) {
00207 Mapping_point_iterator_t hit_point = GetHitPoint(event.GetPosition());
00208 if (hit_point == m_points->end()) {
00209 if (m_active_point != m_points->end()) SetMoving(m_active_point, false);
00210 } else SetMoving(hit_point, (hit_point == m_active_point) ? (false) : (true));
00211 }
00212 }
00213 Refresh();
00214 }
00215 }catch(...)
00216 {
00217
00218 }
00219 }
00220
00221 void TransferFunctionCtrlCanvas::DeletePoint(Mapping_point_iterator_t target)
00222 {
00223 if(target->m_flags == TFP_NONE)
00224 {
00225 m_points->Delete(target);
00226 }
00227
00228 Refresh();
00229 NotifyChange();
00230 }
00231
00232 void TransferFunctionCtrlCanvas::AddNewPoint(const wxPoint &pos)
00233 {
00234 wxColourDialog colour_dlg(this);
00235
00236 if(wxID_OK == colour_dlg.ShowModal())
00237 {
00238 m_points->Add(Mapping_data(Density(pos), Opacity(pos), colour_dlg.GetColourData().GetColour()));
00239 m_points->Sort();
00240
00241 NotifyChange();
00242 }
00243 }
00244
00245 void TransferFunctionCtrlCanvas::AddNewPoint(const wxPoint &pos, const wxColour &colour)
00246 {
00247 m_points->Add(Mapping_data(Density(pos), Opacity(pos), colour));
00248
00249 NotifyChange();
00250 }
00251
00252 void TransferFunctionCtrlCanvas::SetMoving(Mapping_point_iterator_t target, bool holding)
00253 {
00254 m_active_point = holding ? target : m_points->end();
00255
00256 Refresh();
00257 }
00258
00259 void TransferFunctionCtrlCanvas::SetPointPosition(Mapping_point_iterator_t point, const wxPoint &pos)
00260 {
00261 int secure_x;
00262 int secure_y = std::min<int>(std::max<int>(pos.y, 0), GetCanvasHeight());
00263
00264 switch (point->m_flags) {
00265 case TFP_START:
00266 secure_x = 0;
00267 break;
00268 case TFP_END:
00269 secure_x = GetCanvasWidth();
00270 break;
00271 case TFP_NONE:
00272 secure_x = std::min<int>(std::max<int>(pos.x, 0), GetCanvasWidth());
00273 break;
00274 default:
00275 break;
00276 }
00277
00278 SetPosition(point, wxPoint(secure_x, secure_y));
00279
00280 NotifyChange();
00281 Refresh();
00282 }
00283
00284 void TransferFunctionCtrlCanvas::NotifyChange()
00285 {
00286 wxTransferFunctionEvent event(
00287 wxEVT_COMMAND_TRANSFERFUNCTION_CHANGED,
00288 GetId());
00289
00290 event.SetEventObject(this);
00291 GetEventHandler()->ProcessEvent(event);
00292 }