Document domain parameter of wxTranslations::GetTranslatedString().
[wxWidgets.git] / samples / docview / view.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/docview/view.cpp
3 // Purpose: View classes implementation
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin: merge with the MDI version and general cleanup
6 // Created: 04/01/98
7 // Copyright: (c) 1998 Julian Smart
8 // (c) 2008 Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #if !wxUSE_DOC_VIEW_ARCHITECTURE
24 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
25 #endif
26
27 #include "docview.h"
28 #include "doc.h"
29 #include "view.h"
30
31 // ----------------------------------------------------------------------------
32 // DrawingView implementation
33 // ----------------------------------------------------------------------------
34
35 IMPLEMENT_DYNAMIC_CLASS(DrawingView, wxView)
36
37 BEGIN_EVENT_TABLE(DrawingView, wxView)
38 EVT_MENU(wxID_CUT, DrawingView::OnCut)
39 END_EVENT_TABLE()
40
41 // What to do when a view is created. Creates actual
42 // windows for displaying the view.
43 bool DrawingView::OnCreate(wxDocument *doc, long flags)
44 {
45 if ( !wxView::OnCreate(doc, flags) )
46 return false;
47
48 MyApp& app = wxGetApp();
49 if ( app.GetMode() != MyApp::Mode_Single )
50 {
51 // create a new window and canvas inside it
52 wxFrame* frame = app.CreateChildFrame(this, true);
53 wxASSERT(frame == GetFrame());
54 m_canvas = new MyCanvas(this);
55 frame->Show();
56 }
57 else // single document mode
58 {
59 // reuse the existing window and canvas
60 m_canvas = app.GetMainWindowCanvas();
61 m_canvas->SetView(this);
62
63 // Initialize the edit menu Undo and Redo items
64 doc->GetCommandProcessor()->SetEditMenu(app.GetMainWindowEditMenu());
65 doc->GetCommandProcessor()->Initialize();
66 }
67
68 return true;
69 }
70
71 // Sneakily gets used for default print/preview as well as drawing on the
72 // screen.
73 void DrawingView::OnDraw(wxDC *dc)
74 {
75 dc->SetPen(*wxBLACK_PEN);
76
77 // simply draw all lines of all segments
78 const DoodleSegments& segments = GetDocument()->GetSegments();
79 for ( DoodleSegments::const_iterator i = segments.begin();
80 i != segments.end();
81 ++i )
82 {
83 const DoodleLines& lines = i->GetLines();
84 for ( DoodleLines::const_iterator j = lines.begin();
85 j != lines.end();
86 ++j )
87 {
88 const DoodleLine& line = *j;
89
90 dc->DrawLine(line.x1, line.y1, line.x2, line.y2);
91 }
92 }
93 }
94
95 DrawingDocument* DrawingView::GetDocument()
96 {
97 return wxStaticCast(wxView::GetDocument(), DrawingDocument);
98 }
99
100 void DrawingView::OnUpdate(wxView* sender, wxObject* hint)
101 {
102 wxView::OnUpdate(sender, hint);
103 if ( m_canvas )
104 m_canvas->Refresh();
105 }
106
107 // Clean up windows used for displaying the view.
108 bool DrawingView::OnClose(bool deleteWindow)
109 {
110 if ( !wxView::OnClose(deleteWindow) )
111 return false;
112
113 Activate(false);
114
115 // Clear the canvas in single-window mode in which it stays alive
116 if ( wxGetApp().GetMode() == MyApp::Mode_Single )
117 {
118 m_canvas->ClearBackground();
119 m_canvas->ResetView();
120 m_canvas = NULL;
121
122 if (GetFrame())
123 wxStaticCast(GetFrame(), wxFrame)->SetTitle(wxTheApp->GetAppDisplayName());
124 }
125 else // not single window mode
126 {
127 if ( deleteWindow )
128 {
129 GetFrame()->Destroy();
130 SetFrame(NULL);
131 }
132 }
133 return true;
134 }
135
136 void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) )
137 {
138 DrawingDocument * const doc = GetDocument();
139
140 doc->GetCommandProcessor()->Submit(new DrawingRemoveSegmentCommand(doc));
141 }
142
143 // ----------------------------------------------------------------------------
144 // TextEditView implementation
145 // ----------------------------------------------------------------------------
146
147 IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView)
148
149 BEGIN_EVENT_TABLE(TextEditView, wxView)
150 EVT_MENU(wxID_COPY, TextEditView::OnCopy)
151 EVT_MENU(wxID_PASTE, TextEditView::OnPaste)
152 EVT_MENU(wxID_SELECTALL, TextEditView::OnSelectAll)
153 END_EVENT_TABLE()
154
155 bool TextEditView::OnCreate(wxDocument *doc, long flags)
156 {
157 if ( !wxView::OnCreate(doc, flags) )
158 return false;
159
160 wxFrame* frame = wxGetApp().CreateChildFrame(this, false);
161 wxASSERT(frame == GetFrame());
162 m_text = new wxTextCtrl(frame, wxID_ANY, "",
163 wxDefaultPosition, wxDefaultSize,
164 wxTE_MULTILINE);
165 frame->Show();
166
167 return true;
168 }
169
170 void TextEditView::OnDraw(wxDC *WXUNUSED(dc))
171 {
172 // nothing to do here, wxTextCtrl draws itself
173 }
174
175 bool TextEditView::OnClose(bool deleteWindow)
176 {
177 if ( !wxView::OnClose(deleteWindow) )
178 return false;
179
180 Activate(false);
181
182 if ( wxGetApp().GetMode() == MyApp::Mode_Single )
183 {
184 m_text->Clear();
185 }
186 else // not single window mode
187 {
188 if ( deleteWindow )
189 {
190 GetFrame()->Destroy();
191 SetFrame(NULL);
192 }
193 }
194 return true;
195 }
196
197 // ----------------------------------------------------------------------------
198 // MyCanvas implementation
199 // ----------------------------------------------------------------------------
200
201 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
202 EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
203 END_EVENT_TABLE()
204
205 // Define a constructor for my canvas
206 MyCanvas::MyCanvas(wxView *view, wxWindow *parent)
207 : wxScrolledWindow(parent ? parent : view->GetFrame())
208 {
209 m_view = view;
210 m_currentSegment = NULL;
211 m_lastMousePos = wxDefaultPosition;
212
213 SetCursor(wxCursor(wxCURSOR_PENCIL));
214
215 // this is completely arbitrary and is done just for illustration purposes
216 SetVirtualSize(1000, 1000);
217 SetScrollRate(20, 20);
218
219 SetBackgroundColour(*wxWHITE);
220 }
221
222 MyCanvas::~MyCanvas()
223 {
224 delete m_currentSegment;
225 }
226
227 // Define the repainting behaviour
228 void MyCanvas::OnDraw(wxDC& dc)
229 {
230 if ( m_view )
231 m_view->OnDraw(& dc);
232 }
233
234 // This implements a tiny doodling program. Drag the mouse using the left
235 // button.
236 void MyCanvas::OnMouseEvent(wxMouseEvent& event)
237 {
238 if ( !m_view )
239 return;
240
241 wxClientDC dc(this);
242 PrepareDC(dc);
243
244 dc.SetPen(*wxBLACK_PEN);
245
246 const wxPoint pt(event.GetLogicalPosition(dc));
247
248 // is this the end of the current segment?
249 if ( m_currentSegment && event.LeftUp() )
250 {
251 if ( !m_currentSegment->IsEmpty() )
252 {
253 // We've got a valid segment on mouse left up, so store it.
254 DrawingDocument * const
255 doc = wxStaticCast(m_view->GetDocument(), DrawingDocument);
256
257 doc->GetCommandProcessor()->Submit(
258 new DrawingAddSegmentCommand(doc, *m_currentSegment));
259
260 doc->Modify(true);
261 }
262
263 wxDELETE(m_currentSegment);
264 }
265
266 // is this the start of a new segment?
267 if ( m_lastMousePos != wxDefaultPosition && event.Dragging() )
268 {
269 if ( !m_currentSegment )
270 m_currentSegment = new DoodleSegment;
271
272 m_currentSegment->AddLine(m_lastMousePos, pt);
273
274 dc.DrawLine(m_lastMousePos, pt);
275 }
276
277 m_lastMousePos = pt;
278 }
279
280 // ----------------------------------------------------------------------------
281 // ImageCanvas implementation
282 // ----------------------------------------------------------------------------
283
284 // Define a constructor for my canvas
285 ImageCanvas::ImageCanvas(wxView* view)
286 : wxScrolledWindow(view->GetFrame())
287 {
288 m_view = view;
289 SetScrollRate( 10, 10 );
290 }
291
292 // Define the repainting behaviour
293 void ImageCanvas::OnDraw(wxDC& dc)
294 {
295 if ( m_view )
296 m_view->OnDraw(& dc);
297 }
298
299 // ----------------------------------------------------------------------------
300 // ImageView implementation
301 // ----------------------------------------------------------------------------
302
303 IMPLEMENT_DYNAMIC_CLASS(ImageView, wxView)
304
305 ImageDocument* ImageView::GetDocument()
306 {
307 return wxStaticCast(wxView::GetDocument(), ImageDocument);
308 }
309
310 bool ImageView::OnCreate(wxDocument* doc, long flags)
311 {
312 if ( !wxView::OnCreate(doc, flags) )
313 return false;
314
315 wxFrame* frame = wxGetApp().CreateChildFrame(this, false);
316 wxASSERT(frame == GetFrame());
317 m_canvas = new ImageCanvas(this);
318 frame->Show();
319
320 return true;
321 }
322
323 void ImageView::OnUpdate(wxView* sender, wxObject* hint)
324 {
325 wxView::OnUpdate(sender, hint);
326 wxImage image = GetDocument()->GetImage();
327 if ( image.IsOk() )
328 {
329 m_canvas->SetVirtualSize(image.GetWidth(), image.GetHeight());
330 }
331 }
332
333 void ImageView::OnDraw(wxDC* dc)
334 {
335 wxImage image = GetDocument()->GetImage();
336 if ( image.IsOk() )
337 {
338 dc->DrawBitmap(wxBitmap(image), 0, 0, true /* use mask */);
339 }
340 }
341
342 bool ImageView::OnClose(bool deleteWindow)
343 {
344 if ( !wxView::OnClose(deleteWindow) )
345 return false;
346
347 Activate(false);
348
349 if ( wxGetApp().GetMode() == MyApp::Mode_Single )
350 {
351 GetDocument()->DeleteContents();
352 }
353 else // not single window mode
354 {
355 if ( deleteWindow )
356 {
357 GetFrame()->Destroy();
358 SetFrame(NULL);
359 }
360 }
361 return true;
362 }
363
364 // ----------------------------------------------------------------------------
365 // ImageDetailsView
366 // ----------------------------------------------------------------------------
367
368 ImageDetailsView::ImageDetailsView(ImageDetailsDocument *doc)
369 : wxView()
370 {
371 SetDocument(doc);
372
373 m_frame = wxGetApp().CreateChildFrame(this, false);
374 m_frame->SetTitle("Image Details");
375
376 wxPanel * const panel = new wxPanel(m_frame);
377 wxFlexGridSizer * const sizer = new wxFlexGridSizer(2, wxSize(5, 5));
378 const wxSizerFlags
379 flags = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL).Border();
380
381 sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &file:"), flags);
382 sizer->Add(new wxStaticText(panel, wxID_ANY, doc->GetFilename()), flags);
383
384 sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &type:"), flags);
385 wxString typeStr;
386 switch ( doc->GetType() )
387 {
388 case wxBITMAP_TYPE_PNG:
389 typeStr = "PNG";
390 break;
391
392 case wxBITMAP_TYPE_JPEG:
393 typeStr = "JPEG";
394 break;
395
396 default:
397 typeStr = "Unknown";
398 }
399 sizer->Add(new wxStaticText(panel, wxID_ANY, typeStr), flags);
400
401 sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &size:"), flags);
402 wxSize size = doc->GetSize();
403 sizer->Add(new wxStaticText(panel, wxID_ANY,
404 wxString::Format("%d*%d", size.x, size.y)),
405 flags);
406
407 sizer->Add(new wxStaticText(panel, wxID_ANY, "Number of unique &colours:"),
408 flags);
409 sizer->Add(new wxStaticText(panel, wxID_ANY,
410 wxString::Format("%lu", doc->GetNumColours())),
411 flags);
412
413 sizer->Add(new wxStaticText(panel, wxID_ANY, "Uses &alpha:"), flags);
414 sizer->Add(new wxStaticText(panel, wxID_ANY,
415 doc->HasAlpha() ? "Yes" : "No"), flags);
416
417 panel->SetSizer(sizer);
418 m_frame->SetClientSize(panel->GetBestSize());
419 m_frame->Show(true);
420 }
421
422 void ImageDetailsView::OnDraw(wxDC * WXUNUSED(dc))
423 {
424 // nothing to do here, we use controls to show our information
425 }
426
427 bool ImageDetailsView::OnClose(bool deleteWindow)
428 {
429 if ( wxGetApp().GetMode() != MyApp::Mode_Single && deleteWindow )
430 {
431 delete m_frame;
432 m_frame = NULL;
433 }
434
435 return true;
436 }