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