Merge branch '1.0' into 1.0-3D-take2
[dcpomatic.git] / src / wx / audio_mapping_view.cc
1 /*
2     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <wx/wx.h>
21 #include <wx/renderer.h>
22 #include <wx/grid.h>
23 #include <libdcp/types.h>
24 #include "lib/audio_mapping.h"
25 #include "lib/util.h"
26 #include "audio_mapping_view.h"
27 #include "wx_util.h"
28
29 using std::cout;
30 using std::list;
31 using boost::shared_ptr;
32
33 /* This could go away with wxWidgets 2.9, which has an API call
34    to find these values.
35 */
36
37 #ifdef __WXMSW__
38 #define CHECKBOX_WIDTH 16
39 #define CHECKBOX_HEIGHT 16
40 #else
41 #define CHECKBOX_WIDTH 20
42 #define CHECKBOX_HEIGHT 20
43 #endif
44
45 class NoSelectionStringRenderer : public wxGridCellStringRenderer
46 {
47 public:
48         void Draw (wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool)
49         {
50                 wxGridCellStringRenderer::Draw (grid, attr, dc, rect, row, col, false);
51         }
52 };
53
54 class CheckBoxRenderer : public wxGridCellRenderer
55 {
56 public:
57
58         void Draw (wxGrid& grid, wxGridCellAttr &, wxDC& dc, const wxRect& rect, int row, int col, bool)
59         {
60                 dc.SetPen (*wxThePenList->FindOrCreatePen (wxColour (255, 255, 255), 0, wxPENSTYLE_SOLID));
61                 dc.DrawRectangle (rect);
62                 
63                 wxRendererNative::Get().DrawCheckBox (
64                         &grid,
65                         dc, rect,
66                         grid.GetCellValue (row, col) == wxT("1") ? static_cast<int>(wxCONTROL_CHECKED) : 0
67                         );
68         }
69
70         wxSize GetBestSize (wxGrid &, wxGridCellAttr &, wxDC &, int, int)
71         {
72                 return wxSize (CHECKBOX_WIDTH + 4, CHECKBOX_HEIGHT + 4);
73         }
74         
75         wxGridCellRenderer* Clone () const
76         {
77                 return new CheckBoxRenderer;
78         }
79 };
80
81
82 AudioMappingView::AudioMappingView (wxWindow* parent)
83         : wxPanel (parent, wxID_ANY)
84 {
85         _grid = new wxGrid (this, wxID_ANY);
86
87         _grid->CreateGrid (0, 7);
88         _grid->HideRowLabels ();
89         _grid->DisableDragRowSize ();
90         _grid->DisableDragColSize ();
91         _grid->EnableEditing (false);
92         _grid->SetCellHighlightPenWidth (0);
93         _grid->SetDefaultRenderer (new NoSelectionStringRenderer);
94
95         set_column_labels ();
96
97         _sizer = new wxBoxSizer (wxVERTICAL);
98         _sizer->Add (_grid, 1, wxEXPAND | wxALL);
99         SetSizerAndFit (_sizer);
100
101         Connect (wxID_ANY, wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler (AudioMappingView::left_click), 0, this);
102 }
103
104 void
105 AudioMappingView::left_click (wxGridEvent& ev)
106 {
107         if (ev.GetCol() == 0) {
108                 return;
109         }
110         
111         if (_grid->GetCellValue (ev.GetRow(), ev.GetCol()) == wxT("1")) {
112                 _grid->SetCellValue (ev.GetRow(), ev.GetCol(), wxT("0"));
113         } else {
114                 _grid->SetCellValue (ev.GetRow(), ev.GetCol(), wxT("1"));
115         }
116
117         _map = AudioMapping (_map.content_channels ());
118         
119         for (int i = 0; i < _grid->GetNumberRows(); ++i) {
120                 for (int j = 1; j < _grid->GetNumberCols(); ++j) {
121                         if (_grid->GetCellValue (i, j) == wxT ("1")) {
122                                 _map.add (i, static_cast<libdcp::Channel> (j - 1));
123                         }
124                 }
125         }
126
127         Changed (_map);
128 }
129
130 void
131 AudioMappingView::set (AudioMapping map)
132 {
133         _map = map;
134         
135         if (_grid->GetNumberRows ()) {
136                 _grid->DeleteRows (0, _grid->GetNumberRows ());
137         }
138
139         _grid->InsertRows (0, _map.content_channels ());
140
141         for (int r = 0; r < _map.content_channels(); ++r) {
142                 for (int c = 1; c < 7; ++c) {
143                         _grid->SetCellRenderer (r, c, new CheckBoxRenderer);
144                 }
145         }
146         
147         for (int i = 0; i < _map.content_channels(); ++i) {
148                 _grid->SetCellValue (i, 0, wxString::Format (wxT("%d"), i + 1));
149
150                 list<libdcp::Channel> const d = _map.content_to_dcp (i);
151                 for (list<libdcp::Channel>::const_iterator j = d.begin(); j != d.end(); ++j) {
152                         int const c = static_cast<int>(*j) + 1;
153                         if (c < _grid->GetNumberCols ()) {
154                                 _grid->SetCellValue (i, c, wxT("1"));
155                         }
156                 }
157         }
158 }
159
160 void
161 AudioMappingView::set_channels (int c)
162 {
163         c++;
164
165         if (c < _grid->GetNumberCols ()) {
166                 _grid->DeleteCols (c, _grid->GetNumberCols() - c);
167         } else if (c > _grid->GetNumberCols ()) {
168                 _grid->InsertCols (_grid->GetNumberCols(), c - _grid->GetNumberCols());
169                 set_column_labels ();
170         }
171
172         set (_map);
173 }
174
175 void
176 AudioMappingView::set_column_labels ()
177 {
178         int const c = _grid->GetNumberCols ();
179         
180         _grid->SetColLabelValue (0, _("Content channel"));
181         
182         if (c > 0) {
183                 _grid->SetColLabelValue (1, _("L"));
184         }
185         
186         if (c > 1) {
187                 _grid->SetColLabelValue (2, _("R"));
188         }
189         
190         if (c > 2) {
191                 _grid->SetColLabelValue (3, _("C"));
192         }
193         
194         if (c > 3) {
195                 _grid->SetColLabelValue (4, _("Lfe"));
196         }
197         
198         if (c > 4) {
199                 _grid->SetColLabelValue (5, _("Ls"));
200         }
201         
202         if (c > 5) {
203                 _grid->SetColLabelValue (6, _("Rs"));
204         }
205
206         _grid->AutoSize ();
207 }